PRE-GEN

ToG codes

Status: draft, for libraries 0.14.0 (not released yet) · The full rule: TOG-CODE.md · Test vectors: tog-code.json · License: Apache-2.0 · The text is the rule; a vector that disagrees with it gets fixed.

A ToG code is the number of a person, a licence or an act in a registry. Every code is written with one marker, TOG-, and has exactly one spelling. A code is a handle, never a proof: what proves something is a signed record that fits the file.

Old PG- codes Codes issued as PG- keep their meaning forever. They are read as input and become TOG- with the same number and the same check: PG-PRAM-000037J is TOG-PRAM-000037J. No registry writes PG- again. The old format is kept, frozen, on PG codes.

1 · Shapes

  • A person
    TOG-PRAM-900000037K
  • A licence
    TOG-LIC-KAST-ZZZZ-FJ4Y-SM2N
  • An output generated with the person's yes, under their own terms
    TOG-PG-PRAM-ZZZZ-K6X4-RZJB
  • An output generated under a licence
    TOG-PG-LIC-NWRD-PRAM-ZZZZ-VGDY-WCWV
  • A file the person approved after it was made (AFTER-GEN), under their terms
    TOG-AG-PRAM-ZZZZ-T8JE-WDJX
  • A file approved after it was made, under a licence
    TOG-AG-LIC-NWRD-PRAM-ZZZZ-ZJGH-HQH3

A person's code has no kind: TOG-, the registry's prefix, nine digits and a check character. Every other code is an event and starts with its kind. A tail starting ZZZZ marks an example from the specification: it is never issued, so every event example on this page is one.

The five kinds

KindMeansDigit
PGgenerated under the person's standing terms1
PG-LICgenerated under a licence2
AGapproved after generation, under the person's terms3
AG-LICapproved after generation, under a licence4
LICthe licence itself5

The kind's digit goes into the check character, so turning one kind into another (PG into AG, or dropping -LIC) is caught as a mistyped code.

2 · Alphabet and check character

Numbers, tails and check characters use Crockford base32, without I, L, O and U, which are easy to misread:

0123456789ABCDEFGHJKMNPQRSTVWXYZ

Prefixes use all 26 letters. In a TOG body a character's value is its position in this table, where I, L, O and U take 32 to 35:

0123456789ABCDEFGHJKMNPQRSTVWXYZILOU

The check character is the same algorithm as before: each body character's value times its position, counted from 1, summed, mod 37.

sum   = Σ value(body[i]) × (i + 1)
check = "0123456789ABCDEFGHJKMNPQRSTVWXYZ*~$=!"[sum mod 37]

Worked example, the person TOG-PRAM-900000037K. The body is the prefix and the number, without TOG- and dashes: PRAM900000037.

P 22×1 + R 24×2 + A 10×3 + M 20×4 + 9×5 + 3×12 + 7×13 = 352
352 mod 37 = 19  →  K

A new code always ends in a letter or a digit, never in * ~ $ = !: a registry skips any number whose check would be a symbol. The symbols stay valid only in old codes respelled from PG-.

What the check covers

  • TOG-PRAM-900000037K
    body PRAM900000037
  • TOG-PG-PRAM-ZZZZ-K6X4-RZJB
    body 401PRAM + ZZZZK6X4RZJ
  • TOG-PG-LIC-NWRD-PRAM-ZZZZ-VGDY-WCWV
    body 442NWRDPRAM + ZZZZVGDYWCW

An event body starts with the length of each prefix (0 when there is no second one) and the kind's digit, then the prefixes and the tail. So every single wrong character, every swap of two neighbours, every change of kind and every moved dash between two prefixes changes the check.

3 · Person codes

TOG-<PREFIX>-<9 digits><check>
  • The number is exactly nine digits, not starting with 0, picked at random among the registry's unused numbers. A gap means nothing: there is no registration order to read.
  • A dropped or doubled digit gives 8 or 10 digits, which is not a code.
  • One person never has two codes. A person born as PG- keeps their number and check, written with TOG-.

4 · Event codes

TOG-<KIND>-<ISSUER>[-<HOME>]-XXXX-XXXX-XXXX
  • The issuer is the registry that signed the act, and the registry to ask.
  • The home is the person's own registry. It is shown only when it differs from the issuer and the person allows it.
  • The tail is the first 55 bits of the signed record's message id, then the check: three groups of four. The grouping is part of the code, not a display form.
  • The person is never in an event code, and the AI service is never in any code.

An event code is computed from its record, never read off a string. A verifier recomputes it from the signed record and refuses a code that differs. Ten files made under one yes show one code, each with its own file hash.

5 · Old PG- codes

Written beforeRead as
PG-PRAM-000037JTOG-PRAM-000037J
PG-000042*TOG-000042*
PG-STD-000123TOG-STD-000123
PG-SUB-000123TOG-SUB-000123
  • A person's old code folds by its marker only: PG- becomes TOG-, nothing else changes. Every comparison, lookup and refusal check uses that one spelling, so one person never has two records and a refusal cannot be bypassed by spelling.
  • An old licence number, like PG-STD-000001-K7M2QX9, folds through its registry's record into that licence's TOG-LIC code. Without the record the answer is: ask its registry.
  • A PG- string that has no valid TOG spelling was never issued in any spelling: it is not a code.

6 · One code, one string

  • In a message a code has one form: ASCII, upper case, nothing around it. Verifiers and registries never trim, change case or fold look-alikes. A registry answers anything else with PG_MALFORMED, never with a signed answer.
  • Only where a person types, pastes or scans a code may software fold it, and then it shows the result as "Did you mean …?". tog-pram-9OOOOOO37k typed into a search box is TOG-PRAM-900000037K. When two readings are valid, neither is chosen.
  • A code whose check fails is reported as mistyped, apart from not found and from not a code: the three mean different things to whoever holds the code.

7 · Look it up, never take it apart

Software may read from a code only its marker, its kind, the LIC marker and its prefixes. The first prefix is always the registry to ask. Everything else is resolved through that registry, never parsed. Offline, a string alone can say: well formed or mistyped, which kind, under a licence or not, which registry to ask, and whether it is an example. It cannot say that the act happened.

8 · Prefixes

  • 4 to 8 letters A–Z, written only under TOG-. A prefix never starts or ends with LIC.
  • One prefix per legal entity. A government's prefix contains GOV, and no other prefix does.
  • The steward refuses a prefix one edit away from a listed one, one that reads like a marker or a kind, and one with a reserved word in it. A prefix is never reassigned.

Which registry may sign for a prefix is decided by the directory, signed by the steward key. A prefix printed in a code proves nothing by itself.

9 · Testing an implementation

An implementation is correct when it reproduces every case in tog-code.json: check characters, the reading of each string, must-reject strings, the TOG spelling of old codes, typed input, codes computed from records, and copies in a file's metadata. The file is generated from the reference model, never edited by hand. @pregen/verify and pregen implement it from version 0.14.0, which is not released yet; 0.13 reads only PG- codes.