Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 21 additions & 2 deletions packages/iid-spec/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,25 @@ import vectors from '@0xintuition/iid-spec/conformance/canonicalization.json'
**Class C — derived** (a hash of the few facts we actually have)
[`gen1`](./schemes/gen1.md)

## Typed Wikidata identifiers

[`wd`](./schemes/wd.md) is a value-typed scheme: bare `int:wd:Q42` remains polymorphic and floors at P1; active `<slug>:Q…` bindings carry the type and qualify for P0. The active slugs are `film`, `television-series`, and `human`. Dormant bindings remain valid for parsing and validation but are not mintable. URLs canonicalize to bare QIDs and never infer a slug.

The reference implementation reports typing per value:

```ts
import { inspectIntuitionId } from '@0xintuition/iid'

inspectIntuitionId('int:wd:Q42')
// { valid: true, typing: 'polymorphic', anchorEligible: false,
// anchorIneligibilityReason: 'polymorphic-scheme', … }

inspectIntuitionId('int:wd:film:Q188035')
// { valid: true, typing: 'unambiguous', anchorEligible: true, wdSlug: 'film', … }
```

The binding table and canonicalization rules are in [`schemes/wd.md`](./schemes/wd.md); per-value typing is defined in [§7.3](./spec/07-representation-profiles.md). This additive extension follows [§9.3.1](./spec/09-registry-governance.md), preserving existing bare identifiers and their eligibility.

## The conformance corpus

The [`conformance/`](./conformance/) directory is the machine-readable half of this specification. Every vector is normative, generated from the reference implementation, and cross-checked against the golden values stated in the specification prose.
Expand All @@ -84,7 +103,7 @@ The [`conformance/`](./conformance/) directory is the machine-readable half of t
| `gen1.json` | Full `gen1` derivations: recipe fields, exact preimage, and resulting IID |
| `parse.json` | Grammar/parsing vectors, including colon-bearing values and rejections |
| `validation.json` | Full-IID validity and P0 anchor-eligibility vectors |
| `schemes.json` | The registry snapshot: identity class and scheme typing per scheme |
| `schemes.json` | The registry snapshot: identity class, scheme typing, and optional `valueTyped` marker per scheme |

Fixture files are versioned (`specVersion`, `fixtureVersion`) and append-only: changing an existing vector's expected output is an identity-impacting change and follows the governance process in [§9](./spec/09-registry-governance.md).

Expand All @@ -101,7 +120,7 @@ Every test vector in this specification is executable against the reference impl

## Status

**Version 0.1.0 — Draft.** The grammar, the class system, NORM-1, and the `gen1` algorithm are stable and in production use. Scheme canonicalization rules are frozen under the [freeze rule](./spec/09-registry-governance.md): once ratified, a scheme's rules never change in place — a change ships as a new scheme name or version.
**Version 0.1.0 — Draft.** The grammar, the class system, NORM-1, and the `gen1` algorithm are stable and in production use. Scheme canonicalization rules are frozen under the [freeze rule](./spec/09-registry-governance.md): changes to existing canonical values require a new scheme name or version; additive value-grammar extensions follow [§9.3.1](./spec/09-registry-governance.md).

This specification is published for review and adoption. It is not yet submitted to any standards body.

Expand Down
98 changes: 98 additions & 0 deletions packages/iid-spec/conformance/canonicalization.json
Original file line number Diff line number Diff line change
Expand Up @@ -709,6 +709,104 @@
"raw": "movie:r4:FB681AFE7D438CAD73AE90A70F1CC55A",
"canonical": null,
"note": "hash must be lowercase"
},
{
"id": "canon-wd-102",
"scheme": "wd",
"raw": "film:q42",
"canonical": "film:Q42",
"note": "typed QID uppercases"
},
{
"id": "canon-wd-103",
"scheme": "wd",
"raw": " \tfilm:q42\r\n",
"canonical": "film:Q42",
"note": "edge whitespace trims"
},
{
"id": "canon-wd-104",
"scheme": "wd",
"raw": "https://www.wikidata.org/wiki/Q188035",
"canonical": "Q188035",
"note": "URL remains bare; never infers a slug"
},
{
"id": "canon-wd-105",
"scheme": "wd",
"raw": "bogus:Q1",
"canonical": null,
"note": "unknown binding rejects"
},
{
"id": "canon-wd-106",
"scheme": "wd",
"raw": "written-worK:Q42",
"canonical": null,
"note": "non-ASCII slug rejects before case folding"
},
{
"id": "canon-wd-107",
"scheme": "wd",
"raw": "film:Q42",
"canonical": "film:Q42",
"note": "U+FEFF trims like other edge whitespace (base behavior preserved)"
},
{
"id": "canon-wd-108",
"scheme": "wd",
"raw": "film:Q042",
"canonical": null,
"note": "typed QID leading zero rejects"
},
{
"id": "canon-wd-109",
"scheme": "wd",
"raw": "FILM:q42",
"canonical": "film:Q42",
"note": "ASCII slug lowercases"
},
{
"id": "canon-wd-110",
"scheme": "wd",
"raw": "written-work:q42",
"canonical": "written-work:Q42",
"note": "dormant binding remains canonical and parse-only"
},
{
"id": "canon-wd-111",
"scheme": "wd",
"raw": "Q42",
"canonical": "Q42",
"note": "BOM-wrapped bare QID keeps its base canonicalization"
},
{
"id": "canon-isni-url-112",
"scheme": "isni",
"raw": "https://isni.org/isni/0000000121032683",
"canonical": "0000000121032683",
"note": "ISNI URL prefix strips to the existing bare canonical value (section 9.3.1)"
},
{
"id": "canon-isni-url-113",
"scheme": "isni",
"raw": "https://www.isni.org/isni/0000000121032683",
"canonical": "0000000121032683",
"note": "ISNI URL accepts the www host alias"
},
{
"id": "canon-isni-url-114",
"scheme": "isni",
"raw": "HTTPS://ISNI.ORG/isni/0000000121032683",
"canonical": "0000000121032683",
"note": "ISNI URL scheme and host are case-insensitive"
},
{
"id": "canon-isni-url-115",
"scheme": "isni",
"raw": "https://isni.org/ISNI/0000000121032683",
"canonical": "0000000121032683",
"note": "ISNI URL path segment is matched case-insensitively as well (whole-prefix fold, as the reference implementation does)"
}
]
}
14 changes: 14 additions & 0 deletions packages/iid-spec/conformance/parse.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,20 @@
"scheme": null,
"value": null,
"note": "value exceeds 220-char limit"
},
{
"id": "parse-012",
"input": "int:wd:film:Q188035",
"scheme": "wd",
"value": "film:Q188035",
"note": "typed Wikidata value survives first-two-colon split"
},
{
"id": "parse-013",
"input": "int:wd:Q42",
"scheme": "wd",
"value": "Q42",
"note": "legacy bare Wikidata parse remains unchanged"
}
]
}
10 changes: 9 additions & 1 deletion packages/iid-spec/conformance/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,10 @@
"id": { "$ref": "#/$defs/vectorId" },
"iid": { "type": "string" },
"valid": { "type": "boolean" },
"typing": {
"enum": ["unambiguous", "polymorphic"],
"description": "Effective typing of THIS identifier; permitted only for a scheme marked `valueTyped`; defaults to the scheme's typing."
},
"anchorEligible": {
"type": "boolean",
"description": "Whether the IID may be minted as a bare P0 anchor (spec §7.2)."
Expand All @@ -163,7 +167,11 @@
"additionalProperties": false,
"properties": {
"class": { "enum": ["A", "B", "C"] },
"typing": { "enum": ["unambiguous", "polymorphic"] }
"typing": { "enum": ["unambiguous", "polymorphic"] },
"valueTyped": {
"type": "boolean",
"description": "Bare values are polymorphic, but a value MAY carry the entity type inside the value (spec §7.3); validation vectors for such a scheme MAY state per-value typing."
}
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion packages/iid-spec/conformance/schemes.json
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,8 @@
},
"wd": {
"class": "A",
"typing": "polymorphic"
"typing": "polymorphic",
"valueTyped": true
}
}
}
55 changes: 54 additions & 1 deletion packages/iid-spec/conformance/validation.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
"iid": "int:wd:Q42",
"valid": true,
"anchorEligible": false,
"note": "valid but polymorphic — floors at P1"
"note": "valid but bare — polymorphic, floors at P1"
},
{
"id": "valid-007",
Expand Down Expand Up @@ -100,6 +100,59 @@
"valid": true,
"anchorEligible": true,
"note": "strong acct form is anchor eligible"
},
{
"id": "valid-015",
"iid": "int:wd:film:Q188035",
"valid": true,
"typing": "unambiguous",
"anchorEligible": true,
"note": "active film binding is P0 eligible"
},
{
"id": "valid-016",
"iid": "int:wd:human:Q42",
"valid": true,
"typing": "unambiguous",
"anchorEligible": true,
"note": "active human binding is P0 eligible"
},
{
"id": "valid-017",
"iid": "int:wd:written-work:Q47461344",
"valid": true,
"typing": "unambiguous",
"anchorEligible": false,
"note": "dormant written-work binding is valid but not mintable"
},
{
"id": "valid-018",
"iid": "int:wd:film:q42",
"valid": false,
"anchorEligible": false,
"note": "typed QID must be canonical byte-exactly"
},
{
"id": "valid-019",
"iid": "int:wd:bogus:Q1",
"valid": false,
"anchorEligible": false,
"note": "unknown binding rejects"
},
{
"id": "valid-020",
"iid": "int:wd:television-series:Q137400033",
"valid": true,
"typing": "unambiguous",
"anchorEligible": true,
"note": "active television series binding is P0 eligible"
},
{
"id": "valid-isni-url",
"iid": "int:isni:https://isni.org/isni/0000000121032683",
"valid": false,
"anchorEligible": false,
"note": "ISNI URL is accepted raw input but is not a canonical IID value"
}
]
}
2 changes: 1 addition & 1 deletion packages/iid-spec/schemes/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ This directory is the normative scheme registry referenced by [§9.1](../spec/09
| [`gtin`](./gtin.md) | A | T1 | unambiguous | A trade item (product) |
| [`doi`](./doi.md) | A | T1 | polymorphic | A registered digital object |
| [`eidr`](./eidr.md) | A | T1 | unambiguous | An audiovisual work |
| [`wd`](./wd.md) | A | T2 | polymorphic | Any Wikidata entity |
| [`wd`](./wd.md) | A | T2 | polymorphic (bare) · unambiguous (typed, active binding) | Any Wikidata entity (value-typed) |
| [`mbid`](./mbid.md) | A | T2 | unambiguous | A MusicBrainz entity (type in-value) |
| [`olid`](./olid.md) | A | T2 | unambiguous | An OpenLibrary work, edition, or author |
| [`imdb`](./imdb.md) | A | T3 | polymorphic | An IMDb title or name |
Expand Down
6 changes: 6 additions & 0 deletions packages/iid-spec/schemes/isni.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ That is what "polymorphic" means here, and it has a hard consequence: an `isni`

with the additional constraint that the final character is the correct ISO 7064 mod 11-2 check character over the first 15 digits. The grammar alone is not sufficient — a conforming validator recomputes the check character.

## Accepted input forms

The existing bare 16-character form and separator-containing display forms remain accepted. The `https://isni.org/isni/<id>` URL form, with or without `www.`, is also accepted; the whole prefix (scheme, host and the `/isni/` path segment) is matched case-insensitively, so `https://isni.org/ISNI/<id>` is accepted as well; the identifier itself is then canonicalized as below. Strip that URL prefix before applying the existing canonicalization below. Canonical output and existing trim behavior remain unchanged; a URL is an input form, never a canonical IID value.

This follows [§9.3.1](../spec/09-registry-governance.md): an additive value-grammar extension accepts a previously-invalid raw form without changing any existing canonical bytes. The URL form mirrors v2 commit `83a003bc1` (R24, default-in-effect).

## Canonicalization

1. **Strip separators.** Remove every hyphen, dot, and whitespace character (`[-\s.]`). ISNIs are conventionally displayed in four space-separated groups of four; the grouping carries no identity.
Expand Down
Loading
Loading