Problem
An agency has no way to issue its own reference number for an application — the only identifier is the opaque NSW task ID. Where a number is needed it is typed by hand: npqs_application_review's reviewer form has reference_number ("NPQS Reference Number") as a required free-text field, with nothing guaranteeing it is unique, sequential, correctly formatted, or scoped to the issuing office.
Proposed Solution
Adopt github.com/OpenNSW/core/refid, which generates structured sequential IDs from declarative segment config with durable per-scope counters. It is already required in go.mod, and a refIDGen field already exists in cmd/server/config.go but is currently decoded and discarded.
Configuration in two layers:
refIDGen in config.yaml — the ID formats this agency can issue (issuers, segments, lists). Optional; absent means the feature is off for that deployment.
refid in the task config — a new optional block opting one task in:
"refid": {
"issuer": "NPQS",
"idType": "application_id",
"path": "/reference_number",
"params": { "officeCode": "/nppo_office_location" }
}
path is a JSON Pointer into the officer response; params maps a format param to a JSON Pointer into the injected data, so one task config serves every office.
Behaviour:
- Generated once, on first inject only — a re-inject keeps the existing number. (Requires carrying
ReviewerResponse forward past CreateOrUpdate's full-row Save, as ClaimedBy/ClaimedAt already are.)
- Written into
reviewer_response at path, so the officer's review form renders it pre-filled.
- Fail-closed — a generation failure fails the inject, so an application never exists without its number.
- Counters in a new
refid_sequences table (migration 000010), on the existing DB connection.
In one-trade-artifacts: add refid to schemas/taskconfig.schema.json, which sets additionalProperties: false. No form change needed — reference_number already exists as the first control. Whether it is read-only is left to the form author.
Alternatives
- Typed by hand (status quo) — no uniqueness, sequence or format guarantee.
- Generate at review time — the number would not exist while the application is pending, but officers need to quote it before deciding.
- A local generator instead of
core/refid — duplicates a solved problem and lets ID formats diverge per agency.
Follow-ups out of scope
- The number is not visible or searchable in the applications list —
List projects the JSONB columns out and searches only task_id/consignment_id.
- No server-side protection of the field:
FinalizeReview stores whatever the client posts, so an officer can still overwrite the number. A read-only form control is convention, not enforcement — this needs backend validation of the review payload.
Problem
An agency has no way to issue its own reference number for an application — the only identifier is the opaque NSW task ID. Where a number is needed it is typed by hand:
npqs_application_review's reviewer form hasreference_number("NPQS Reference Number") as a required free-text field, with nothing guaranteeing it is unique, sequential, correctly formatted, or scoped to the issuing office.Proposed Solution
Adopt
github.com/OpenNSW/core/refid, which generates structured sequential IDs from declarative segment config with durable per-scope counters. It is already required ingo.mod, and arefIDGenfield already exists incmd/server/config.gobut is currently decoded and discarded.Configuration in two layers:
refIDGeninconfig.yaml— the ID formats this agency can issue (issuers, segments, lists). Optional; absent means the feature is off for that deployment.refidin the task config — a new optional block opting one task in:pathis a JSON Pointer into the officer response;paramsmaps a format param to a JSON Pointer into the injected data, so one task config serves every office.Behaviour:
ReviewerResponseforward pastCreateOrUpdate's full-rowSave, asClaimedBy/ClaimedAtalready are.)reviewer_responseatpath, so the officer's review form renders it pre-filled.refid_sequencestable (migration000010), on the existing DB connection.In
one-trade-artifacts: addrefidtoschemas/taskconfig.schema.json, which setsadditionalProperties: false. No form change needed —reference_numberalready exists as the first control. Whether it is read-only is left to the form author.Alternatives
core/refid— duplicates a solved problem and lets ID formats diverge per agency.Follow-ups out of scope
Listprojects the JSONB columns out and searches onlytask_id/consignment_id.FinalizeReviewstores whatever the client posts, so an officer can still overwrite the number. A read-only form control is convention, not enforcement — this needs backend validation of the review payload.