Groundskeeper
Research

First Australian structured-detector micro-slice: HPI-I and VSN

Status: owner-approved for experimental implementation (G0); see section 17 for the recorded decisions and the implementation. Observe and redact only, through G2; no production blocking. Evidence cut-off: 3 October 2026 (Australia/Sydney) Machine-readable companion: au-structured-detector-micro-slice.json (pinned sources, proposed definitions, 79 synthetic cases) Governing decisions: ADR 0003, ADR 0007, ADR 0010, and the proposed ADR 0011

This document specifies the first real detector pair. Sections 1–16 are the specification as reviewed; section 17 records the owner decisions and how the built-in detectors implement it. Every rule here is written so the expected output can be derived without the Go implementation.

1. Recommendation

Keep the pair:

ClassIdentifierPublic category (proposed)Why it is the right first member
validated_structuredHealthcare Provider Identifier – Individual (HPI-I)privacy.pii.health_id.au.hpi_iA standards body publishes a complete grammar: 16 digits, fixed prefix 800361, and Luhn. A random 16-digit string passes with probability of about 10⁻⁷, so no context gate is needed. Context changes confidence and evidence only, never validation state. Disclosure is restricted by the Healthcare Identifiers Act 2010 s 26(1)(d).
context_bound_structuredVictorian Student Number (VSN)privacy.pii.education_id.au.vic.vsnThe issuer publishes an exact but collision-prone shape: nine digits, the same shape as TFN, ACN, and many reference numbers. The detector is useful only because of an exact issuer label or field, which is the property ADR 0010 must demonstrate. The identifier relates to children and is protected under Part 5.3A of the Victorian Education and Training Reform Act 2006.

Research since the inventory produced three refinements, none of which changes the choice:

  1. VSN has an unpublished check digit. The 2027 Victorian VET collection guidelines say the nine-digit format includes a check digit and refer to an algorithm on the VSN website. No public algorithm was found. VCAA still describes the VSN as randomly generated, which fits a random body plus a check digit. VSN therefore remains context-bound and can never be validated from local evidence. Groundskeeper must not guess the algorithm (compare OD-016 and OD-018).
  2. VSN has published non-identifiers. Valid values are 000000001–999999999. 888888888 is a temporary code for a student who has not yet received a VSN. Both 000000000 and 888888888 are rejected. The standard enrolment form groups the number as 3-3-3, so that grouping is supported.
  3. HPI-I is also legally protected. Section 26(1)(d) of the current compilation (C2026C00415, 19 September 2026) covers the identifier of an individual healthcare provider, not only a patient's IHI. Redacting HPI-I therefore has real privacy value.

Alternatives considered

CandidateClassWhy it was not chosen first
IHI (800360 + Luhn)validatedIt is the strongest alternative. It uses the same mechanics, protects patients, and already has a category. However, nearly every Medicare or DVA enrolee has an IHI: tens of millions of values in a space of about 10⁹ Luhn-valid numbers. A synthetic fixture therefore has a few per cent chance of being a real person's IHI. There are roughly one million HPI-Is, so the chance is about 0.1%. Once the validator exists, IHI only needs a different prefix. Recommended as the immediate follow-on.
HPI-O (800362)validatedThis is an organisational identifier, so it proves less about personal-data handling.
ABNvalidatedIts mod-89 check is weaker: about 1 in 89 random values pass. ABNs are public business identifiers and should not be redacted by default.
MedicarevalidatedIts mod-10 check passes about 1 in 10 random values, and the shape collides with ordinary numbers. It needs context gates, so it does not isolate the "checksum alone" case.
USI, CRN, VIN, ImmiCardvalidated (inventory include)None has a public checksum, so none can exercise the validated state.
Visa Grant Numbercontext-boundThe label is exact, but the source does not constrain the alphabet ("13 characters"), so the shape is too loose to show that the label, not the shape, supplies the evidence. It is a reasonable second context-bound detector.
NSW WWCC, DVA, Ahpra, credit licencecontext-boundOnly a prefix, a maximum length, or examples are published. Completing the grammar would require invention.
VCAA Student Number (8 digits + letter)—It is not in the sourced inventory. It is used here as a hard negative.

2. Compatibility boundary

  • Detectors consume only the canonical segments passed to the existing Detect(ctx, []model.Segment) interface: content_path, media_type, text, and optional role/source. They never read payload or adapter_attributes. This holds whether the concurrent API-drift work keeps payload-only requests or derives segments from them. This proposal assumes no outcome for that work.
  • Output uses only existing finding fields: category, entity_type, severity, confidence, detector_id, detector_version, detector_class, validation_state, location, and evidence. All evidence kinds already exist in common.schema.json. No schema change is needed.
  • The proposed detector IDs are builtin.pii.au.hpi-i and builtin.pii.au-vic.vsn. Both satisfy the current ID pattern. Each detector has one class, its own coverage and version, and can be rolled back independently. The builtin.pii.au detector in policies/examples/au-baseline.yaml remains illustrative.
  • Detectors require no network, filesystem, clock, or randomness permissions. They are deterministic and idempotent, and their runtime is linear in the segment length.

3. Pinned sources

Full records, including claims, licences, and freshness notes, are in the JSON sources object.

KeySourcePinSupports
hl7-au-base-6.0.0-hpiiHL7 Australia AU Base 6.0.0 StructureDefinition-au-hpii.json (CC0)2026-01-15; sha256 d8f3e8d8…a01416 digits, prefix 800361, Luhn (inv-hpii-0..2), system URI. The 7.0.0-ballot1 invariants are unchanged.
adha-practice-manager-handbookADHA My Health Record Handbook for Practice Managers2022-07 (digest not captured)Government corroboration of the prefix and length
health-gov-healthcare-identifiersDepartment of Health, Disability and Ageingpage updated 2025-12-0516-digit identifiers; HPI-I is assigned on Ahpra registration
hi-act-2010-c2026c00415Healthcare Identifiers Act 2010, compilation 222026-09-19; sha256 80e988fc…026es 26(1)(d) use/disclosure restriction and penalties
vcaa-find-out-student-numbersVCAA, Find out about student numbersretrieved 2026-10-03 (dynamic HTML)Random nine-digit VSN; VCAA Student Number is a different identifier
vcaa-vsn-providersVCAA, VSN for Education and Training Providersretrieved 2026-10-03Part 5.3A governs the VSN; no VSNs in class lists
djsir-vvssc-2027DJSIR Victorian VET Student Statistical Collection Guidelines 2027PDF 2026-08-11; sha256 e9e3dc12…b71fLength 9, range, 888888888, existence of a check digit, 3-3-3 form
vic-etr-act-2006-part-5.3aEducation and Training Reform Act 2006 (Vic) Part 5.3Aauthorised version not captureds 5.3A.10 restriction; s 5.3A.13 student self-disclosure

Licensing: only the HL7 guide is CC0, so its invariants may be embedded in machine-readable definitions. All other sources are cited as facts and are not reproduced. Labels such as "Victorian Student Number" are names, not protected expression. Do not use licensed HI Service test data.

4. Taxonomy and identity

HPI-IVSN
Inventory ID → public categoryau.health.hpi_i → privacy.pii.health_id.au.hpi_iau.education.vic_vsn → privacy.pii.education_id.au.vic.vsn
Catalogue object IDgroundskeeper.dev/definition/privacy.pii.health_id.au.hpi_igroundskeeper.dev/definition/privacy.pii.education_id.au.vic.vsn
entity_type aliasAU_HPI_IAU_VIC_VSN
Jurisdiction / issuer levelAU / commonwealthAU + AU-VIC / state
Classificationpersonal; government-related identifier; statutorily restrictedpersonal; government-related identifier; children and young people; statutorily restricted
Provisional severitymediumhigh
Target catalogue file (after ADR 0011)pii-au/definitions/national/health-identifiers.yamlpii-au/definitions/subdivisions/au-vic/education-identifiers.yaml

Rationale: the Healthcare Identifiers Act treats HPI-I as a healthcare identifier. Placing it under health_id, beside ihi, lets a policy that selects all Australian healthcare identifiers include it. The subdivision is a taxonomy level (au.vic) so policies can select Victorian identifiers. ISO 3166-2 remains in metadata (AU-VIC), as ADR 0011 requires.

5. Shared recognition rules

  • Digits: ASCII 0–9 only. Fullwidth digits, other Unicode Nd digits, and format characters (Cf, including zero-width characters) are not folded or skipped in v0. They are measured as known gaps (section 10).
  • Word character: any code point in Unicode category L*, N*, or M*, or Pc (which includes _).
  • Surface forms: contiguous digits, or the documented grouping (HPI-I 4-4-4-4; VSN 3-3-3). Groups are joined by one repeated separator from U+0020, U+00A0, U+202F, U+002D, U+2010, or U+2011. A value cannot mix separators.
  • Value boundary:
    • The code points immediately before and after the value are not word characters.
    • The value is not preceded by . or , with a digit before it, and is not followed by . or , with a digit after it. This excludes decimals and thousands grouping.
    • For grouped forms only, the value is not preceded by a group separator with a digit before it, and is not followed by a group separator with a digit after it. This is the maximal-run rule.
  • Normalization: delete the group separator. Spans still cover the original code points from the first digit to the last, never surrounding labels, punctuation, or whitespace (ADR 0003). The segment text is never rewritten.
  • Label boundary: a label must not be preceded or followed by a word character.
  • Deduplication: each detector emits at most one finding per (content_path, start, end). When several bindings support the same span, their evidence is merged and the higher state is kept.
  • Finding IDs must be unique within a response, for example au-hpi-i-001 and au-vic-vsn-001. The canary detector's finding-%03d scheme would collide once two detectors run.
  • Evidence contains kind, result, method, version, and an optional label-set reference. It never contains a value, a substring, or an unkeyed hash.

6. HPI-I (validated_structured)

  1. Scan every segment as text, including application/json segments.

  2. Accept a value in a supported surface form whose normalized form is 16 digits beginning with 800361.

  3. Luhn: starting from the rightmost digit, double every second digit, subtract 9 from any doubled value above 9, and require the sum of all digits to be divisible by 10. This is equivalent to inv-hpii-2.

  4. If the value passes, emit validation_state: validated with shape/supports and checksum/supports evidence. Otherwise emit nothing. In particular, do not emit for:

    • a Luhn failure, even when labelled;
    • prefix 800360 (IHI), 800362 (HPI-O), or any other prefix;
    • lengths 15 or 17;
    • embedded digits or alphanumeric adjacency.

    HPI-I never emits candidate or probable in v0. Emitting a candidate for a labelled Luhn failure is deferred.

  5. Optional context evidence: this evidence never changes validation state.

    • Proximal label: use the nearest label ending within the 64 code points before the value, with no digit between the label and the value.
      • Supporting labels: HPI-I (hyphen U+002D, U+2010, or U+2011); HPII; and "Healthcare Provider Identifier <dash> Individual" (case-insensitive; the dash may be U+002D, U+2010, U+2011, U+2013, or U+2014).
      • Contradicting labels: IHI, HPI-O, HPIO, HSP-O, and HSPO. These produce context_label/contradicts. The structure still determines the category.
    • Segment URI: if there is no proximal label, the FHIR system URI http://ns.electronichealth.net.au/id/hi/hpii/1.0 anywhere in the segment produces context_label/supports.
    • Field key: if the last decoded pointer token normalizes to hpii or healthcareprovideridentifierindividual, and the trimmed segment is exactly the value, add field_path/supports.
  6. validated means the value is validly formed according to a published check digit. It does not mean the identifier was issued, is current, or belongs to the person in the conversation. The HI Service is never queried.

7. VSN (context_bound_structured)

Value

  • A supported surface form (contiguous or 3-3-3) whose normalized form is 9 digits.
  • Reject 000000000 and 888888888.
  • Leading zeros are significant.
  • No checksum test is performed. The published check digit's algorithm is unavailable, and v0 must not emulate it.

Text binding

The grammar is LABEL SEP VALUE, with label and value boundaries as defined in section 5.

  • Tier A label: victorian HWS+ student HWS+ number, optionally followed by (VSN) with optional internal HWS. Matching is ASCII case-insensitive. HWS is U+0009, U+0020, U+00A0, or U+202F.
  • Tier B label: either VSN in exactly that case, or "vsn" as a double-quoted JSON key in any ASCII case. The quoted form also requires : or U+FF1A in SEP.
  • SEP: S1 [WORD S2].
    • S1 is 0–8 separator characters; S2 is 1–8.
    • WORD is one of is, number, no., or no (ASCII case-insensitive), and is allowed only when S1 is non-empty.
    • Separator characters: HWS, :, =, #, -, U+2013, |, *, ", ', and U+FF1A.
    • Line breaks and zero-width characters are not separators. This deliberately excludes non-adjacent text such as "VSN of the student is …".
  • Corroboration (tier B text bindings only): look in the same segment for a whole-word jurisdiction term lying entirely within [label_start − 200, value_end + 200) code points.
    • Case-insensitive terms: Victoria, Victorian.
    • Exact-case terms: VIC, VCAA, VRQA.

Field binding

  1. Split content_path on /.
  2. Decode ~1 and then ~0 in each token, and take the last token. An all-digit token is an array index and does not match.
  3. Normalize the key: convert it to ASCII lower case, then delete _, -, ., spaces, and /. If any code point outside [a-z0-9] remains, it does not match.
  4. Classify the key: victorianstudentnumber is tier A; vsn is tier B.
  5. Trim leading and trailing HWS and line breaks from the segment text. The result must be exactly one VSN surface form. The span excludes the trimmed whitespace.

Evidence-state semantics

BindingStateEvidence kinds
No binding: bare value, jurisdiction term only, TFN/ACN/"student number"/VCAA label, non-adjacent labelno finding—
Tier A text labelprobableshape, issuer_label, jurisdiction (label-intrinsic)
Tier B text label + corroborationprobableshape, issuer_label, jurisdiction (same-segment term)
Tier B text label, no corroborationcandidateshape, issuer_label
Tier A field keyprobableshape, field_path, jurisdiction
Tier B field keycandidateshape, field_path
Any bindingnever validatedRequires a published checksum or an approved registry

Tier B is candidate because, outside education, "VSN" is an ambiguous acronym (for example, serial or version numbers). A tenant-approved application schema, bound through a future snapshot, is the intended route for raising a tier B field to probable. A detector heuristic is not.

Confidence placeholders in the JSON are uncalibrated. Until OD-019 is decided, policies must trigger on category and validation_state, not minimum_confidence. Conformance tests must not assert confidence values.

8. Eligible segments and paths

  • Scan every segment regardless of role or source. System prompts, tool results, and model output can all contain identifiers. Policy match decides where an action applies.
  • text/plain and application/json are both scanned as text. Spans index the exact JSON text.
    • The Portkey adapter currently splits JSON into one text/plain segment per string, keyed by its JSON Pointer. Field binding uses those pointers.
    • When redacting inside an application/json segment, the replacement must remain a valid JSON string fragment: no ", \, or control characters.
  • Labels and values bind only within one segment. Cross-segment and conversation-level binding is a known gap.
  • Multiple values per segment are supported. List binding such as VSNs: a, b is a known gap. This matters because VCAA specifically prohibits VSNs in class lists.
  • The path is used only for field binding. It is never echoed in evidence beyond the finding's own location.content_path.

9. Overlap expectations

  • Within the slice, HPI-I and VSN spans cannot overlap because their lengths and boundary rules differ. both.pos.disjoint_spans and both.vsn_label_with_hpi_i_value prove this. In the second case, a 16-digit HPI-I after a VSN label yields only the HPI-I finding.
  • Detectors never suppress another detector's findings. With future detectors, the same span may carry several categories. For example, a generic Luhn or payment card detector would also match an HPI-I. Each context-bound detector binds only to its own labels, so identical-span collisions come from validated detectors without context gates. Any future generic Luhn or payment card detector should exclude the 80036[0-2] prefixes or rely on deterministic merge rules.
  • Constraints in the executable slice at review time, verified by reading the code (all three are fixed; see section 17):
    1. ApplyModifications rejects overlapping modifications. A redact profile must therefore not include two categories that can produce the same span until a deterministic merge rule exists.
    2. The evaluator runs a detector once per rule and appends every finding. Two rules that use the same detector in one profile duplicate findings, and two redact rules would produce overlapping modifications. Use one rule per detector per profile.
    3. Finding IDs must be detector-scoped, as described in section 5.

10. Fixtures

The JSON contains 79 cases built from the canonical segment shape. Every wrapped request validates against evaluation-request.schema.json.

GroupPositiveNegativeKnown gap (gold-sensitive, no v0 finding)
HPI-I12126
VSN181613
Cross-detector2——

The cases produce 16 HPI-I validated findings, 17 VSN probable findings, and 3 VSN candidate findings. Six cases tagged adr0010_pair reuse a positive VSN value with no label, a jurisdiction term only, or a TFN, ACN, "student number", or wrong field label. Each must produce no finding.

Coverage by slice

  • Unicode and spacing:
    • offsets after a ZWJ emoji sequence;
    • CJK text with fullwidth colons;
    • U+00A0 separators;
    • tabs and multiple spaces in labels;
    • Markdown bold and pipe tables;
    • quoted JSON keys;
    • escaped pointer tokens (~1);
    • trimmed field values;
    • punctuation adjacent to values.
  • Hard negatives:
    • Luhn failure;
    • IHI, HPI-O, and other 8003 prefixes;
    • card test number 4111…;
    • lengths 8, 10, 15, and 17;
    • embedded digits, alphanumeric adjacency, and decimals;
    • five-group and four-group continuations;
    • comma grouping;
    • AVSN/myVSN;
    • Erlang {vsn, …};
    • VCAA Student Number;
    • both sentinels;
    • text that is not a value in a VSN field;
    • generic student_number keys.
  • Known gaps (adversarial/evasion):
    • fullwidth and Arabic-Indic digits;
    • zero-width characters inside values or after labels;
    • combining marks;
    • Cyrillic homoglyph VЅN;
    • spaced V S N;
    • lowercase prose vsn;
    • plural VSNs;
    • value-before-label;
    • line breaks after labels;
    • non-adjacent labels;
    • unsupported groupings;
    • mixed separators;
    • cross-segment labels;
    • array-element fields.

How the fixtures were checked

Values were chosen by hand. Spans were computed from explicit markers, never by a detector.

  • The three synthetic HPI-Is and the HL7 published example pass Luhn; the invalid fixture fails it.
  • A throwaway reference reading of sections 5–7 agreed with all 79 expectations, and a mutated expectation was correctly rejected. That script was not committed: it is not a detector, and the conformance guide still calls for an independently authored reference evaluator.

Privacy of fixture values

Fixtures use three HPI-I-valid values and three VSN-shaped values. None is paired with a name, date of birth, school, or practice. Checksum-valid synthetic values are not guaranteed to be unissued. The estimated chance that a given value is real is about 0.1% for HPI-I and below 1% for VSN.

11. Privacy constraints

  • Synthetic data only, until privacy approval covers real-traffic observation. Section 26 of the HI Act and s 5.3A.10 of the ETR Act restrict use and disclosure. Legal review must confirm the deploying organisation's and the operator's roles before Groundskeeper processes real traffic containing these identifiers. Self-disclosure by a student (s 5.3A.13) is not a basis for retaining a value.
  • Metadata-only telemetry (ADR 0007): counts by category, state, tier, and rejection reason (for example checksum_rejected or sentinel_rejected). Never values, substrings, unkeyed hashes, or path fragments beyond the finding location. Keyed fingerprints are off by default (OD-009).
  • Errors contain no input. Coverage messages are fixed strings.
  • Redaction replacements are fixed category tokens that encode nothing about the value. Reversible tokenisation is excluded (OD-010).
  • No remote validation: neither the HI Service nor the Victorian Student Register is queried.
  • No external judges receive fixtures or traffic (OD-008).
  • No inference is made about people, schools, communities, or Indigeneity. The fixtures contain no names or community material (ADR 0008).

12. Benchmark methodology

  1. Partitions follow conformance and benchmarking:
    • public development: this JSON;
    • private fixed holdout: produced by a seeded template generator, authored and held by someone other than the detector implementer;
    • incident-derived cases: later, under the separate privacy process.
  2. Generators combine templates, values, and perturbations, and label from the template, never from detector output. They cover:
    • every surface form, label tier, separator, segment type, and role/source;
    • every hard-negative family in section 10;
    • known-gap perturbations as a separate evasion slice.
  3. Benign background: synthetic numeric-heavy text without identifiers, such as logs, CSV and spreadsheets, invoices and orders, code, and phone and banking formats. Reuse public-domain prose only after a licence check. Report findings per million code points. The analytic HPI-I expectation for random digits is about 10⁻⁷ per 16-digit window.
  4. Metrics:
    • exact type-and-span precision, recall, and F1 by category, state, tier, and slice;
    • post-redaction leakage (any gold digit remaining) and over-redaction (code points outside gold spans);
    • zero rate on bare-value ADR 0010 pairs;
    • known-gap recall, reported but not gated;
    • latency at p50/p99 per KiB and allocations;
    • determinism across repeated runs.
  5. Statistics:
    • Wilson 95% intervals for proportions.
    • The rule of three for zero-error claims: zero false positives in n trials bounds the rate below 3/n at 95%.
    • McNemar's test and paired bootstrap for version comparisons.
  6. Reproducibility: pin the generator seed, corpus hash, spec version, detector version, and policy digest. Store raw outputs with values redacted.

13. Provisional non-production gates

Numbers marked † are proposals for OD-004 and OD-019 owners, not decisions.

GateEvidence requiredPermits
G0: implementation merge100% of committed fixtures match (category, class, state, span, evidence kind/result multiset)ADR 0010 invariants pass on all outputs (section 14)no values in findings, errors, logs, or metrics (canary test)race and fuzz clean, deterministic outputmanifest declares one class and no permissionsDetector code merged and disabled by default
G1: observeG0holdout precision and recall = 1.0 on supported forms (deterministic rules: any miss is a defect)zero findings on ADR 0010 pairs and hard negativeszero false positives on ≥ 10⁶ benign 16-digit windows (HPI-I) and ≥ 10⁵ benign labelled-negative contexts (VSN)†p99 latency budget characterised†action: record, required: false, on_error: continue_unjudged on synthetic traffic, or real traffic only after privacy and legal approval of processing roles and metadata telemetry
G2: redactG1zero leakage and zero over-redaction on supported formsno overlapping-modification errors with the profile under testreplacement tokens approved (OD-010)triggers fixed at HPI-I validated and VSN probableNon-production or limited canary redaction. Best effort against accidental disclosure, explicitly not evasion-resistant
G3: block or production enforcementG2OD-004 thresholds by risk tierOD-019 confidence calibration on approved representative dataOD-005 and OD-006 error posturedecision and measured recall for the evasion slicereal-traffic precision with a lower 95% bound at the agreed tier, from privacy-approved metadata reviewlegal sign-off (HI Act s 26, ETR Act Part 5.3A)rollback drill and owner approvalVSN tier B precision measured before any promotion to probableBlocking, required: true, or production enforcement

Observe and redact are permitted only up to G2 and outside production enforcement. Nothing in this slice authorises blocking.

An illustrative policy bundle follows. It validates against policy-bundle.schema.json. At review time it was not committed because the detectors did not exist; the implemented equivalent is policies/examples/au-baseline.yaml (section 17):

bundle_version: "1.0"
name: dev.groundskeeper.examples.au-structured-micro-slice
version: 0.0.1
profiles:
  observe:
    composition: deny_wins
    rules:
      - id: observe_au_hpi_i
        check: { detector: builtin.pii.au.hpi-i, timeout_ms: 50 }
        required: false
        on_error: continue_unjudged
        trigger: { categories: [privacy.pii.health_id.au.hpi_i], minimum_validation: validated }
        action: { type: record }
      - id: observe_au_vic_vsn
        check: { detector: builtin.pii.au-vic.vsn, timeout_ms: 50 }
        required: false
        on_error: continue_unjudged
        trigger: { categories: [privacy.pii.education_id.au.vic.vsn], minimum_validation: candidate }
        action: { type: record }
  redact:
    composition: deny_wins
    rules:
      - id: redact_au_hpi_i
        check: { detector: builtin.pii.au.hpi-i, timeout_ms: 50 }
        required: false
        on_error: continue_unjudged
        trigger: { categories: [privacy.pii.health_id.au.hpi_i], minimum_validation: validated }
        action: { type: redact, replacement: "[AU_HPI_I]" }
      - id: redact_au_vic_vsn
        check: { detector: builtin.pii.au-vic.vsn, timeout_ms: 50 }
        required: false
        on_error: continue_unjudged
        trigger: { categories: [privacy.pii.education_id.au.vic.vsn], minimum_validation: probable }
        action: { type: redact, replacement: "[AU_VIC_VSN]" }

14. How the pair proves ADR 0010

ADR 0010 requirementProof in this slice
The classes are explicit in manifests and findingsEach detector's manifest declares exactly one class, and every finding carries detector_class.
Context-bound detectors emit nothing without a label or field (and jurisdiction)The adr0010_pair cases, plus bare-value, sentinel, and other-label negatives
Syntax alone supports candidate; adding context supports probableVSN tier B (candidate) versus tier A or corroborated (probable)
validated only from a published checksum or approved lookupHPI-I validated requires checksum/supports. A Luhn failure produces nothing. VSN is never validated, even with a label.
Class does not redefine state, and context does not change a validated stateHPI-I with supporting, contradicting, or no context is always validated.
Confidence is calibrated separately per classSeparate placeholders, and a policy rule that forbids confidence triggers until OD-019
Inventory include → validated; context_only → context-bound; categories mapped before shippingau.health.hpi_i (include) and au.education.vic_vsn (context_only), with the mappings in section 4

The following invariants must hold for every output, checked mechanically:

  • validated ⇒ some checksum or reference_match evidence has result supports.
  • context_bound_structured ⇒ some issuer_label, context_label, or field_path evidence has result supports.
  • VSN probable ⇒ there is jurisdiction/supports evidence or a tier A binding.

15. Decisions needed

  1. Pair: approve HPI-I + VSN (recommended), or start with IHI to gain patient value at the cost of higher fixture-collision risk.
  2. Taxonomy: approve privacy.pii.health_id.au.hpi_i and privacy.pii.education_id.au.vic.vsn, including the subdivision level, and extend the initial taxonomy table.
  3. VSN tier B: keep VSN and "vsn" without corroboration as candidate (recommended), or treat them as probable outright.
  4. Unicode stance: accept ASCII-only v0, with folding and obfuscation measured as known gaps. This must be revisited before G3.
  5. Privacy and legal (OD-010 and related):
    • provisional severities and replacement tokens;
    • processing roles under the HI Act and ETR Act before any real traffic;
    • whether to request the VSN check-digit algorithm from VCAA as an approved source. Obtaining it privately would not by itself justify validated.
  6. Gates: set the numbers marked † (OD-004 and OD-019).

16. Follow-ups

  • The inventory's VSN record says "None published" for the checksum. That remains accurate, but the record should cite djsir-vvssc-2027 for the check digit's existence and the 888888888 code. Adding a source changes the inventory invariants enforced by scripts/validate-contracts.sh, so the change is left for a reviewed inventory update.
  • No catalog/ package was created. ADR 0011 is still Proposed, and no catalogue schema exists to validate against. Once both are approved, move the JSON definitions and cases into catalog/packages/groundskeeper.dev/pii-au and convert them to the package test format.

17. Owner decisions and implementation record

Decisions recorded on 3 October 2026

The owner approved the following answers to section 15. They are provisional where marked and do not settle any open decision named below.

QuestionDecision
PairHPI-I as the validated_structured detector plus the exact-labelled Victorian Student Number as the context_bound_structured detector.
TaxonomyProvisional public categories privacy.pii.health_id.au.hpi_i and privacy.pii.education_id.au.vic.vsn, including the au.vic subdivision level.
VSN tier BThe bare VSN acronym or a "vsn" key without Victorian or VCAA context is candidate only.
Unicode stanceASCII digits only in v0. Unicode-digit and format-character evasion is measured and documented as a known gap, and must be revisited before G3.
Permitted useObserve and redact experimental use only, up to and including G2.
EnforcementNo production blocking until legal and privacy review and G3.
Severities and tokensThe provisional severities (medium, high) and the final redaction-token policy remain governed by OD-010. [AU_HPI_I] and [AU_VIC_VSN] are experimental placeholders.

Executable-slice invariants fixed before the detectors

The three constraints listed at the end of section 9 no longer apply:

  1. One execution per detector. The evaluator runs each detector referenced by an enabled rule exactly once per request and reports its findings once. Every referencing rule judges the shared output and gets its own coverage entry. The shared run uses the longest referencing timeout; a rule whose own timeout_ms was exceeded is timed_out and applies its on_error.
  2. Deterministic redaction merge. Overlapping or identical redactions with the same replacement merge into their union and carry the sorted union of finding IDs. Touching spans stay separate. Overlapping redactions with different replacements fail closed: the decision becomes block, no modification is returned, and coverage and unjudged gain a failed evaluation.modifications entry with reason conflicting_modifications. The two micro-slice detectors cannot produce overlapping spans, so the example profiles never reach this path.
  3. Response-wide finding IDs. The evaluator assigns finding-NNN IDs after ordering findings by content path, span, detector ID, and category. IDs are unique across detectors and deterministic for a given request and policy, independent of rule order. Detector-local IDs (au-hpi-i-NNN, au-vic-vsn-NNN) are not exposed.

Section 2's compatibility note is also settled: canonical requests are now segments-authoritative and payload is rejected, so detectors only ever see canonical segments.

Implementation

  • Detectors: builtin.pii.au.hpi-i and builtin.pii.au-vic.vsn in internal/checks/pii, version 0.1.0, implementing sections 5–7 exactly. They are registered as built-ins but run only when the active policy profile references them. The default development policy does not, so they are disabled by default (G0).
  • Policy: policies/examples/au-baseline.yaml now loads in the runtime with an observe profile (record; HPI-I validated, VSN candidate) and a redact-experimental profile (HPI-I validated, VSN probable). Every rule is required: false, on_error: continue_unjudged, and overridable: false, and no rule uses minimum_confidence (OD-019). See policy bundles.
  • Privacy: detectors never log. Evidence carries only fixed method and version strings. Coverage messages are fixed. Tests serialize complete output and assert that no value or fragment appears in it or in HTTP responses.

Validation

CheckWhere
All 79 cases match category, class, state, span, and evidence kind/result multiset (16 HPI-I validated, 17 VSN probable, 3 VSN candidate)internal/checks/pii (detectors) and internal/app (full observe pipeline, request and response schemas)
Definitions agree with detector constants: IDs, categories, entity types, classes, severities, prefix, excluded VSN valuesinternal/checks/pii
Section 14 ADR 0010 invariants on every emitted finding, including fuzzed outputinternal/checks/pii
Case counts, unique IDs, and the 32/28/19 splitscripts/validate-contracts.sh
Duplicate-rule, timeout, overlap-merge, conflict, and finding-ID regressionsinternal/evaluation
au-baseline.yaml loads for every profile within the G2 posture; overridable is retainedinternal/policy
Redaction through canonical and Portkey routes, including field bindinginternal/app
Fuzzing (determinism, valid spans on ASCII digits, Luhn/sentinel validity, no overlap, invariants), race, and latencyinternal/checks/pii, internal/evaluation, internal/app

Latency was characterised on 64 KiB of adversarial, label- and digit-dense text on a 2-vCPU orb: about 1 ms for HPI-I and 2–3 ms for VSN, linear in input size (about 25 µs and 38 µs per KiB). A regression test fails above 100 ms per 64 KiB. This is a characterisation, not the OD-004 latency SLO.

Known gaps (v0, documented and measured)

  • Unicode digits, fullwidth digits, zero-width and other format characters, combining marks, and homoglyph labels evade detection. The 19 known-gap fixtures and 12 generated perturbations all evade v0 (recall 0/19 and 0/12).
  • Lowercase prose vsn, plural VSNs, list binding, value-before-label, line breaks after labels, non-adjacent labels, cross-segment labels, and array-element fields are not bound.
  • HPI-I does not emit a candidate for a labelled Luhn failure.
  • check.config is not passed to built-in detectors in this slice.
  • Built-in detectors have no manifest file yet; the class is a code constant and is carried on every finding.
  • Holdout, benign-background, and real-traffic measurements required by G1 and later gates have not been run.

On this page