@indorania/contracts 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. package/README.md +117 -0
  2. package/dist/common.d.ts +144 -0
  3. package/dist/common.d.ts.map +1 -0
  4. package/dist/common.js +162 -0
  5. package/dist/common.js.map +1 -0
  6. package/dist/constitution/index.d.ts +9 -0
  7. package/dist/constitution/index.d.ts.map +1 -0
  8. package/dist/constitution/index.js +9 -0
  9. package/dist/constitution/index.js.map +1 -0
  10. package/dist/constitution/openapi.d.ts +23 -0
  11. package/dist/constitution/openapi.d.ts.map +1 -0
  12. package/dist/constitution/openapi.js +375 -0
  13. package/dist/constitution/openapi.js.map +1 -0
  14. package/dist/constitution/report.d.ts +63 -0
  15. package/dist/constitution/report.d.ts.map +1 -0
  16. package/dist/constitution/report.js +73 -0
  17. package/dist/constitution/report.js.map +1 -0
  18. package/dist/constitution/tables.d.ts +53 -0
  19. package/dist/constitution/tables.d.ts.map +1 -0
  20. package/dist/constitution/tables.js +96 -0
  21. package/dist/constitution/tables.js.map +1 -0
  22. package/dist/constitution/words.d.ts +39 -0
  23. package/dist/constitution/words.d.ts.map +1 -0
  24. package/dist/constitution/words.js +126 -0
  25. package/dist/constitution/words.js.map +1 -0
  26. package/dist/document.d.ts +12 -0
  27. package/dist/document.d.ts.map +1 -0
  28. package/dist/document.js +106 -0
  29. package/dist/document.js.map +1 -0
  30. package/dist/domain-error.d.ts +14 -0
  31. package/dist/domain-error.d.ts.map +1 -0
  32. package/dist/domain-error.js +23 -0
  33. package/dist/domain-error.js.map +1 -0
  34. package/dist/index.d.ts +24 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +24 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/op.d.ts +92 -0
  39. package/dist/op.d.ts.map +1 -0
  40. package/dist/op.js +113 -0
  41. package/dist/op.js.map +1 -0
  42. package/dist/routes/asks.d.ts +77 -0
  43. package/dist/routes/asks.d.ts.map +1 -0
  44. package/dist/routes/asks.js +182 -0
  45. package/dist/routes/asks.js.map +1 -0
  46. package/dist/routes/backup.d.ts +12 -0
  47. package/dist/routes/backup.d.ts.map +1 -0
  48. package/dist/routes/backup.js +63 -0
  49. package/dist/routes/backup.js.map +1 -0
  50. package/dist/routes/capabilities.d.ts +67 -0
  51. package/dist/routes/capabilities.d.ts.map +1 -0
  52. package/dist/routes/capabilities.js +88 -0
  53. package/dist/routes/capabilities.js.map +1 -0
  54. package/dist/routes/entitlements.d.ts +137 -0
  55. package/dist/routes/entitlements.d.ts.map +1 -0
  56. package/dist/routes/entitlements.js +101 -0
  57. package/dist/routes/entitlements.js.map +1 -0
  58. package/dist/routes/guest.d.ts +57 -0
  59. package/dist/routes/guest.d.ts.map +1 -0
  60. package/dist/routes/guest.js +140 -0
  61. package/dist/routes/guest.js.map +1 -0
  62. package/dist/routes/integration.d.ts +187 -0
  63. package/dist/routes/integration.d.ts.map +1 -0
  64. package/dist/routes/integration.js +243 -0
  65. package/dist/routes/integration.js.map +1 -0
  66. package/dist/routes/meta.d.ts +50 -0
  67. package/dist/routes/meta.d.ts.map +1 -0
  68. package/dist/routes/meta.js +90 -0
  69. package/dist/routes/meta.js.map +1 -0
  70. package/dist/routes/organisations.d.ts +121 -0
  71. package/dist/routes/organisations.d.ts.map +1 -0
  72. package/dist/routes/organisations.js +175 -0
  73. package/dist/routes/organisations.js.map +1 -0
  74. package/dist/routes/presentations.d.ts +95 -0
  75. package/dist/routes/presentations.d.ts.map +1 -0
  76. package/dist/routes/presentations.js +121 -0
  77. package/dist/routes/presentations.js.map +1 -0
  78. package/dist/routes/sessions.d.ts +180 -0
  79. package/dist/routes/sessions.d.ts.map +1 -0
  80. package/dist/routes/sessions.js +240 -0
  81. package/dist/routes/sessions.js.map +1 -0
  82. package/dist/routes/standing.d.ts +24 -0
  83. package/dist/routes/standing.d.ts.map +1 -0
  84. package/dist/routes/standing.js +74 -0
  85. package/dist/routes/standing.js.map +1 -0
  86. package/dist/routes/thank-yous.d.ts +30 -0
  87. package/dist/routes/thank-yous.d.ts.map +1 -0
  88. package/dist/routes/thank-yous.js +139 -0
  89. package/dist/routes/thank-yous.js.map +1 -0
  90. package/dist/versions.d.ts +46 -0
  91. package/dist/versions.d.ts.map +1 -0
  92. package/dist/versions.js +54 -0
  93. package/dist/versions.js.map +1 -0
  94. package/dist/webhooks.d.ts +55 -0
  95. package/dist/webhooks.d.ts.map +1 -0
  96. package/dist/webhooks.js +76 -0
  97. package/dist/webhooks.js.map +1 -0
  98. package/dist/zod.d.ts +3 -0
  99. package/dist/zod.d.ts.map +1 -0
  100. package/dist/zod.js +7 -0
  101. package/dist/zod.js.map +1 -0
  102. package/node/kernel-esm.mjs +27 -0
  103. package/node/register.mjs +5 -0
  104. package/openapi/2026-09-25.json +6959 -0
  105. package/openapi/versions.json +10 -0
  106. package/package.json +49 -0
package/README.md ADDED
@@ -0,0 +1,117 @@
1
+ # @indorania/contracts
2
+
3
+ The platform contract — every route, schema, error, dated version and webhook that a member or an outside issuer builds against (ECOSYSTEM decision 47, PLATFORM-SESSIONS PL-4). **One contract:** a member integrates exactly as a stranger would.
4
+
5
+ **Status:** version 0.1.0, the package's first version. API version `2026-09-25` is still labelled **preview** in its document (`x-indorania-version-status`). By the founder's rule of 2026-09-25 (see **Versions**), publishing this package is that version's first release, so treat it as released — changes by addition only — even though the label has not yet been changed to `released`. 55 operations and 2 webhooks are wired in `apps/api`. **27 are built** (PL-7, 2026-09-26): the version list and the documents, accounts and organisations, houses, seats, entitlements, capabilities and sections, the integration's own side, the encrypted backup, the trust list and the webhook keys, and the guest countersign. The other 28 answer `501 not_built` and name, as `x-indorania-pending`, the session that builds them: PL-8. PL-7 added five operations to the preview — `createIntegration` and the guest's own four (`openGuestLink`, `submitGuestAcceptance`, `getGuestPage`, `getCeremonyModule`) — and `did`, `review` and `clientId` to three shapes; a preview may be corrected in place, and the pinned hash moved with it.
6
+
7
+ ## What is here
8
+
9
+ | Path | What |
10
+ |---|---|
11
+ | `openapi/2026-09-25.json` | The generated OpenAPI 3.1 document, committed. **This is the contract.** |
12
+ | `openapi/versions.json` | Every version: its status, and the SHA-256 of its document's exact bytes |
13
+ | `src/routes/*.ts` | The Zod schemas and operations, one file per resource. The source of the document |
14
+ | `src/versions.ts` | The dated-version registry and the version-change layer |
15
+ | `src/constitution/` | The lints, as checks over an OpenAPI document or a table model (`@indorania/contracts/constitution`) |
16
+ | `src/webhooks.ts` | The reference signer and verifier for webhooks (`@indorania/contracts/webhooks`) |
17
+ | `node/` | A Node resolve hook for a defect in the published kernel — see **The kernel** below |
18
+
19
+ ```sh
20
+ pnpm --filter @indorania/contracts build # emit dist/, regenerate openapi/
21
+ pnpm --filter @indorania/contracts check # the committed documents equal the schemas
22
+ pnpm --filter @indorania/contracts lint # the constitution, over every committed document
23
+ pnpm --filter @indorania/contracts test
24
+ ```
25
+
26
+ ## Using it: install the package, or vendor the document
27
+
28
+ Install `@indorania/contracts` from npm, or **vendor the OpenAPI file, pinned by version and hash** — the file is `openapi/<version>.json` in this package. Never path-link it (ECOSYSTEM d10, d19):
29
+
30
+ 1. Copy `openapi/<version>.json` into your repository, byte for byte, with LF line endings. In `.gitattributes`: `<path> text eol=lf`.
31
+ 2. Record the version and the `sha256` from `openapi/versions.json`.
32
+ 3. In your CI, recompute the file's SHA-256 and fail if it differs.
33
+
34
+ A preview's hash changes whenever it is corrected. A released version's hash changes only when something is added to it.
35
+
36
+ ## Versions
37
+
38
+ - **Where the version lives.** The URL carries the major version (`/v1`). Every request speaks a dated version: send `Indorania-Version: YYYY-MM-DD`, or your organisation's or integration's pinned version applies. With neither, the request is refused (`400 version_required`). Webhooks reach you in your pinned version.
39
+ - **Preview.** A version is a preview until its first release, when the founder publishes this package or a member first vendors the document (founder decision, 2026-09-25). Until then it may still be corrected in place.
40
+ - **Released.** Inside a released version, changes are additive only: new operations, new optional fields, new enum values, new problem codes. Treat anything unknown gracefully. Any other change is a new dated version. Its `VersionChange` translates requests up and responses and webhooks down, so a pinned caller never sees it.
41
+ - **Not built yet:** an automated additive-only check, and the change of `2026-09-25`'s label from `preview` to `released`.
42
+ - **Exempt from dated versions:**
43
+ - the OpenID4VCI and OpenID4VP endpoints — their standards version them, and a stranger's wallet never sends our header
44
+ - documents that describe themselves: the trust list, the webhook keys, the version list, and these documents
45
+
46
+ ## Errors
47
+
48
+ Errors are RFC 9457 problem details, served as `application/problem+json`:
49
+ - `type` is `https://kashscript.com/indorania/problems/<code>`. It is an identifier and is never fetched.
50
+ - `code` is stable and machine-readable.
51
+ - `errors[]` carries `{path, message, rule}`. `rule` names a published rule when one is broken — for example an ask's `R8-no-improvement-item` or `FORBIDDEN-NEED`, or a house's `OPEN-DOOR`.
52
+
53
+ ## Idempotency
54
+
55
+ Every change made through this API carries an `Idempotency-Key`: IETF draft-07, a quoted string, and the bare form is also accepted. A UUID is right. Keys are kept 24 hours:
56
+
57
+ | When | Answer |
58
+ |---|---|
59
+ | no key | 400 `idempotency_key_required` |
60
+ | the same key and body again | the first answer again |
61
+ | the same key with another body | 422 `idempotency_key_reused` |
62
+ | the same key while the first request still runs | 409 `idempotency_in_progress` |
63
+
64
+ Standard-protocol endpoints rely on their own single-use code or nonce, and webhooks rely on `webhook-id`. Every mutation declares which, as `x-indorania-idempotency`. **The requirement is enforced, and storage and replay are built (PL-7):** a change's key is kept 24 hours under a hash of its caller, so nothing that names the caller is stored.
65
+
66
+ ## Webhooks, both directions
67
+
68
+ Standard Webhooks 1.0.0, scheme `v1a` (Ed25519):
69
+ - **Signing.** The signature covers `webhook-id.webhook-timestamp.body`, over the body's exact bytes. It has a 300-second tolerance. The payload is `{type, timestamp, data}`.
70
+ - **Keys.** Indorania signs with the keys at `GET /v1/webhook-keys`, a JWKS. An integration signs its deliveries — `POST /v1/integration/predicate-answers` — with a key it registered.
71
+ - **Rotation.** During a rotation a message carries one signature per key, and any one valid signature is enough.
72
+
73
+ `@indorania/contracts/webhooks` has the reference `signWebhook` and `verifyWebhook`, with a fixed test vector (`test/webhooks.test.ts`).
74
+
75
+ ## Who calls
76
+
77
+ | Scheme | Who | How |
78
+ |---|---|---|
79
+ | `seat` | a staff login, acting through a seat in an organisation | an OIDC access token: authorization code with PKCE, after a passkey sign-in (ADR-0002) |
80
+ | `integration` | a member's or an outside issuer's system | client-credentials bearer, via a `private_key_jwt` assertion (RFC 7523) |
81
+ | `personAccount` | a person's optional account | a passkey, and the bearer session token it gives; reaches `/v1/backup` only (ADR-0001, ADR-0002) |
82
+ | `relationshipProof` | a person's wallet, with no account | a DPoP proof (RFC 9449) signed by the relationship key |
83
+ | `webhookSignature` | a webhook, either way | Standard Webhooks `v1a` |
84
+ | none | the ask library, the trust list, standing rules, an invitation (by its join secret), OID4VCI and OID4VP | public |
85
+
86
+ ## What the contract never does
87
+
88
+ These are checked by `pnpm lint`, which runs in CI, over every committed document and over `@indorania/db`'s tables. Each rule has a test that plants a violation and expects it caught.
89
+
90
+ - no origin, ethnicity, sect, caste or descent field (d36)
91
+ - nothing joins a person across relationships. Person-side identifiers are one component, `RelationshipId` (a `did:kash` relationship key), one at a time and never listed (d41, d47(g))
92
+ - nothing lists a house's members, or the houses a person is in (d47(c)). Staff are **seats**, and a house's members are never modelled
93
+ - only allowlisted reads return lists, and none is searched or filtered (d41)
94
+ - entitlements carry capacity, never a meter (d50)
95
+ - a decline has no endpoint, state or field (d49(a))
96
+ - no member is named in structure. Members appear as the capabilities `visits` · `money` · `work` (edge 7)
97
+ - no score, rank, percentage or balance, and nothing on a thank-you adds up
98
+ - no private key, secret or seed in any field
99
+
100
+ ## Decisions this contract makes
101
+
102
+ - **The handoff registration registers an issuer, never an offer.** An issuer registers its OpenID4VCI credential issuer, what it issues, and its signing keys. Wallets redeem offers at the issuer's own host, so no third party learns a relationship key (holder contract §1).
103
+ - **Answers take one of two paths:**
104
+ - A person answers in their wallet, over OpenID4VP, to a presentation request.
105
+ - An organisation answers from its own book: the platform calls the predicate-answer webhook of the integration running that book.
106
+ Only a *yes* reaches a verifier.
107
+ - **A person's account is one encrypted blob** that binds nothing (ADR-0001, `docs/adr/`).
108
+
109
+ ## The kernel
110
+
111
+ The ask schema is built from `@kashscript/attest@0.2.0-alpha.1`'s exported constants, and a publish is checked by attest's own `validateAsk`. Session profiles, the receipt format and the trust-list type come from attest too. That package's tarball ships no `specs/` and no `ask.schema.json`, so its constants are the one published source.
112
+
113
+ **A defect, verified 2026-09-25:** attest (0.1.8 and 0.2.0-alpha.1) and identity-core (0.3.1) ship ES modules whose relative imports have no extension. Their `.d.ts` files do too.
114
+ - **Runtime.** Plain Node cannot load them. Anything here that runs under Node loads `node/register.mjs` first (`node --import @indorania/contracts/node/register …`), which retries those imports with `.js`, for `@kashscript/*` packages only.
115
+ - **Types.** This package typechecks with `moduleResolution: "Bundler"`, because `NodeNext` sees no exports.
116
+
117
+ Delete the hook when KashScript republishes with `.js` specifiers.
@@ -0,0 +1,144 @@
1
+ /**
2
+ * The shapes every resource shares: identifiers, the person-side identifier, the envelope a signed
3
+ * record travels in, the one error envelope, and pages.
4
+ */
5
+ import { z } from "./zod.ts";
6
+ export declare const ID_PREFIXES: {
7
+ readonly organisation: "org";
8
+ readonly seat: "seat";
9
+ readonly grant: "grant";
10
+ readonly integration: "int";
11
+ readonly session: "ses";
12
+ readonly presentationRequest: "preq";
13
+ readonly answer: "ans";
14
+ readonly thankYou: "ty";
15
+ readonly book: "book";
16
+ };
17
+ export type IdPrefix = (typeof ID_PREFIXES)[keyof typeof ID_PREFIXES];
18
+ export declare function newId(prefix: IdPrefix): string;
19
+ export declare const OrganisationId: z.ZodString;
20
+ export declare const SeatId: z.ZodString;
21
+ export declare const GrantId: z.ZodString;
22
+ export declare const IntegrationId: z.ZodString;
23
+ export declare const SessionId: z.ZodString;
24
+ export declare const PresentationRequestId: z.ZodString;
25
+ export declare const AnswerId: z.ZodString;
26
+ export declare const ThankYouId: z.ZodString;
27
+ export declare const BookRef: z.ZodString;
28
+ /**
29
+ * The only person-side identifier in this contract (ECOSYSTEM d41, d47(g)). A person is known to
30
+ * the platform, if at all, only inside one relationship: this is the `did:kash` of a key the
31
+ * person's wallet made for that relationship alone. It is never a global id, and no operation
32
+ * takes two of them, lists them, or joins one to another.
33
+ */
34
+ export declare const RelationshipId: z.ZodString;
35
+ /** An organisation's or an issuer's signing identifier. Organisations are public parties. */
36
+ export declare const OrgDid: z.ZodString;
37
+ export declare const UnixTime: z.ZodNumber;
38
+ export declare const HttpsUrl: z.ZodURL;
39
+ /** Words a person or a staff member reads. Short, and plain (Indorania CLAUDE.md, technical rule 9). */
40
+ export declare function words(max: number): z.ZodString;
41
+ /** A DSSE envelope, carried exactly as its signers made it — never re-wrapped or re-signed (holder contract §0). */
42
+ export declare const DsseEnvelope: z.ZodObject<{
43
+ payloadType: z.ZodString;
44
+ payload: z.ZodString;
45
+ signatures: z.ZodArray<z.ZodObject<{
46
+ keyid: z.ZodString;
47
+ sig: z.ZodString;
48
+ }, z.core.$strict>>;
49
+ }, z.core.$strict>;
50
+ /** Problem `type` URIs live in the ecosystem's identifier namespace. They are identifiers, never fetched. */
51
+ export declare const PROBLEM_TYPE_BASE = "https://kashscript.com/indorania/problems/";
52
+ export declare const PROBLEMS: {
53
+ readonly invalid_request: {
54
+ readonly status: 400;
55
+ readonly title: "The request does not match the contract";
56
+ };
57
+ readonly version_required: {
58
+ readonly status: 400;
59
+ readonly title: "Say which API version you speak";
60
+ };
61
+ readonly version_unknown: {
62
+ readonly status: 400;
63
+ readonly title: "That API version does not exist";
64
+ };
65
+ readonly idempotency_key_required: {
66
+ readonly status: 400;
67
+ readonly title: "A change needs an Idempotency-Key";
68
+ };
69
+ readonly idempotency_key_invalid: {
70
+ readonly status: 400;
71
+ readonly title: "The Idempotency-Key is not well formed";
72
+ };
73
+ readonly unauthenticated: {
74
+ readonly status: 401;
75
+ readonly title: "Say who is calling";
76
+ };
77
+ readonly signature_invalid: {
78
+ readonly status: 401;
79
+ readonly title: "The signature does not verify";
80
+ };
81
+ readonly forbidden: {
82
+ readonly status: 403;
83
+ readonly title: "Not allowed for this caller";
84
+ };
85
+ readonly not_found: {
86
+ readonly status: 404;
87
+ readonly title: "Nothing is here";
88
+ };
89
+ readonly idempotency_in_progress: {
90
+ readonly status: 409;
91
+ readonly title: "A request with this Idempotency-Key is still running";
92
+ };
93
+ readonly version_conflict: {
94
+ readonly status: 412;
95
+ readonly title: "It changed since you last read it";
96
+ };
97
+ readonly idempotency_key_reused: {
98
+ readonly status: 422;
99
+ readonly title: "This Idempotency-Key was used for a different request";
100
+ };
101
+ readonly internal: {
102
+ readonly status: 500;
103
+ readonly title: "Something failed on our side";
104
+ };
105
+ readonly not_built: {
106
+ readonly status: 501;
107
+ readonly title: "In the contract, not built yet";
108
+ };
109
+ };
110
+ export type ProblemCode = keyof typeof PROBLEMS;
111
+ export declare const ProblemDetail: z.ZodObject<{
112
+ path: z.ZodString;
113
+ message: z.ZodString;
114
+ rule: z.ZodOptional<z.ZodString>;
115
+ }, z.core.$strict>;
116
+ export declare const Problem: z.ZodObject<{
117
+ type: z.ZodString;
118
+ title: z.ZodString;
119
+ status: z.ZodNumber;
120
+ code: z.ZodString;
121
+ detail: z.ZodOptional<z.ZodString>;
122
+ instance: z.ZodOptional<z.ZodString>;
123
+ errors: z.ZodOptional<z.ZodArray<z.ZodObject<{
124
+ path: z.ZodString;
125
+ message: z.ZodString;
126
+ rule: z.ZodOptional<z.ZodString>;
127
+ }, z.core.$strict>>>;
128
+ }, z.core.$strip>;
129
+ export type Problem = z.infer<typeof Problem>;
130
+ export type ProblemDetail = z.infer<typeof ProblemDetail>;
131
+ export declare function problem(code: ProblemCode, init?: {
132
+ detail?: string;
133
+ instance?: string;
134
+ errors?: ProblemDetail[];
135
+ }): Problem;
136
+ export declare const PageQuery: z.ZodObject<{
137
+ cursor: z.ZodOptional<z.ZodString>;
138
+ limit: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
139
+ }, z.core.$strict>;
140
+ export declare function pageOf<T extends z.ZodType>(item: T, id: string): z.ZodObject<{
141
+ items: z.ZodArray<T>;
142
+ next: z.ZodNullable<z.ZodString>;
143
+ }, z.core.$strict>;
144
+ //# sourceMappingURL=common.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../src/common.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,UAAU,CAAC;AAQ7B,eAAO,MAAM,WAAW;;;;;;;;;;CAUd,CAAC;AAEX,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,OAAO,WAAW,CAAC,CAAC;AAEtE,wBAAgB,KAAK,CAAC,MAAM,EAAE,QAAQ,GAAG,MAAM,CAU9C;AASD,eAAO,MAAM,cAAc,aAA6F,CAAC;AACzH,eAAO,MAAM,MAAM,aAAwI,CAAC;AAC5J,eAAO,MAAM,OAAO,aAAyD,CAAC;AAC9E,eAAO,MAAM,aAAa,aAA+I,CAAC;AAC1K,eAAO,MAAM,SAAS,aAAoG,CAAC;AAC3H,eAAO,MAAM,qBAAqB,aAAiH,CAAC;AACpJ,eAAO,MAAM,QAAQ,aAA0G,CAAC;AAChI,eAAO,MAAM,UAAU,aAAwH,CAAC;AAChJ,eAAO,MAAM,OAAO,aAAuL,CAAC;AAE5M;;;;;GAKG;AACH,eAAO,MAAM,cAAc,aAQvB,CAAC;AAEL,6FAA6F;AAC7F,eAAO,MAAM,MAAM,aAGqE,CAAC;AAIzF,eAAO,MAAM,QAAQ,aAAsE,CAAC;AAE5F,eAAO,MAAM,QAAQ,UAAwE,CAAC;AAE9F,wGAAwG;AACxG,wBAAgB,KAAK,CAAC,GAAG,EAAE,MAAM,eAEhC;AAID,oHAAoH;AACpH,eAAO,MAAM,YAAY;;;;;;;kBAmBrB,CAAC;AAIL,6GAA6G;AAC7G,eAAO,MAAM,iBAAiB,+CAA+C,CAAC;AAE9E,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAeX,CAAC;AAEX,MAAM,MAAM,WAAW,GAAG,MAAM,OAAO,QAAQ,CAAC;AAEhD,eAAO,MAAM,aAAa;;;;kBAMf,CAAC;AAEZ,eAAO,MAAM,OAAO;;;;;;;;;;;;iBAahB,CAAC;AAEL,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,OAAO,CAAC,CAAC;AAC9C,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAE1D,wBAAgB,OAAO,CACrB,IAAI,EAAE,WAAW,EACjB,IAAI,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,aAAa,EAAE,CAAA;CAAO,GAC1E,OAAO,CAWT;AAID,eAAO,MAAM,SAAS;;;kBAKX,CAAC;AAEZ,wBAAgB,MAAM,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM;;;mBAQ9D"}
package/dist/common.js ADDED
@@ -0,0 +1,162 @@
1
+ /**
2
+ * The shapes every resource shares: identifiers, the person-side identifier, the envelope a signed
3
+ * record travels in, the one error envelope, and pages.
4
+ */
5
+ import { z } from "./zod.js";
6
+ // ── Identifiers ────────────────────────────────────────────────────────────────────────────────
7
+ // `<prefix>_<26 Crockford base-32 characters>`: 128 random bits, never time-ordered, so an id
8
+ // carries no creation time and no sequence another party could read.
9
+ const CROCKFORD = "0123456789abcdefghjkmnpqrstvwxyz";
10
+ export const ID_PREFIXES = {
11
+ organisation: "org",
12
+ seat: "seat",
13
+ grant: "grant",
14
+ integration: "int",
15
+ session: "ses",
16
+ presentationRequest: "preq",
17
+ answer: "ans",
18
+ thankYou: "ty",
19
+ book: "book",
20
+ };
21
+ export function newId(prefix) {
22
+ const bytes = crypto.getRandomValues(new Uint8Array(16));
23
+ let bits = 0n;
24
+ for (const byte of bytes)
25
+ bits = (bits << 8n) | BigInt(byte);
26
+ let out = "";
27
+ for (let i = 0; i < 26; i++) {
28
+ out = CROCKFORD[Number(bits & 31n)] + out;
29
+ bits >>= 5n;
30
+ }
31
+ return `${prefix}_${out}`;
32
+ }
33
+ function idSchema(prefix, id, description) {
34
+ return z
35
+ .string()
36
+ .regex(new RegExp(`^${prefix}_[${CROCKFORD}]{26}$`))
37
+ .meta({ id, description, example: `${prefix}_0f5m2c8r1h7k3n9p4q6s2t8v1w` });
38
+ }
39
+ export const OrganisationId = idSchema("org", "OrganisationId", "An organisation: a business, an institute or a house.");
40
+ export const SeatId = idSchema("seat", "SeatId", "A staff login's place in one organisation. For a house, a steward's seat — never a member of the house.");
41
+ export const GrantId = idSchema("grant", "GrantId", "One entitlement grant.");
42
+ export const IntegrationId = idSchema("int", "IntegrationId", "A system that offers a capability through this contract — an ecosystem member's, or an outside issuer's.");
43
+ export const SessionId = idSchema("ses", "SessionId", "One session: one encounter between an establishment and a person.");
44
+ export const PresentationRequestId = idSchema("preq", "PresentationRequestId", "One presentation request, minted for one encounter and used once.");
45
+ export const AnswerId = idSchema("ans", "AnswerId", "One organisation's answer to an ask, routed to the book that answers it.");
46
+ export const ThankYouId = idSchema("ty", "ThankYouId", "One thank-you, as its issuer knows it: an offer and a status index, never the person.");
47
+ export const BookRef = idSchema("book", "BookRef", "An organisation's book at one integration. Pairwise: each integration sees its own reference, so no two integrations can match an organisation by it.");
48
+ /**
49
+ * The only person-side identifier in this contract (ECOSYSTEM d41, d47(g)). A person is known to
50
+ * the platform, if at all, only inside one relationship: this is the `did:kash` of a key the
51
+ * person's wallet made for that relationship alone. It is never a global id, and no operation
52
+ * takes two of them, lists them, or joins one to another.
53
+ */
54
+ export const RelationshipId = z
55
+ .string()
56
+ .regex(/^did:kash:[1-9A-HJ-NP-Za-km-z]{16,128}$/)
57
+ .meta({
58
+ id: "RelationshipId",
59
+ description: "A person's identifier within one relationship: the did:kash of a key their wallet made for that relationship alone. Never a global identifier, never listed, never joined to another relationship (ECOSYSTEM d41, d47(g)).",
60
+ "x-indorania-person-side": true,
61
+ });
62
+ /** An organisation's or an issuer's signing identifier. Organisations are public parties. */
63
+ export const OrgDid = z
64
+ .string()
65
+ .regex(/^did:[a-z0-9]+:[A-Za-z0-9._%:-]+$/)
66
+ .meta({ id: "OrgDid", description: "A DID an organisation or an issuer signs with." });
67
+ // ── Small shared shapes ────────────────────────────────────────────────────────────────────────
68
+ export const UnixTime = z.number().int().min(0).meta({ description: "Unix seconds, UTC." });
69
+ export const HttpsUrl = z.url({ protocol: /^https$/ }).meta({ description: "An https URL." });
70
+ /** Words a person or a staff member reads. Short, and plain (Indorania CLAUDE.md, technical rule 9). */
71
+ export function words(max) {
72
+ return z.string().min(1).max(max);
73
+ }
74
+ const BASE64 = /^[A-Za-z0-9+/_-]*={0,2}$/;
75
+ /** A DSSE envelope, carried exactly as its signers made it — never re-wrapped or re-signed (holder contract §0). */
76
+ export const DsseEnvelope = z
77
+ .object({
78
+ payloadType: z.string().min(1),
79
+ payload: z.string().regex(BASE64).meta({ description: "Base64 of the payload bytes." }),
80
+ signatures: z
81
+ .array(z
82
+ .object({
83
+ keyid: z.string(),
84
+ sig: z.string().regex(BASE64),
85
+ })
86
+ .strict())
87
+ .min(1),
88
+ })
89
+ .strict()
90
+ .meta({
91
+ id: "DsseEnvelope",
92
+ description: "A DSSE envelope (attest's `DsseEnvelope`). Every signature covers PAE(payloadType, payload); the JSON around it is trusted for nothing.",
93
+ });
94
+ // ── The one error envelope ─────────────────────────────────────────────────────────────────────
95
+ /** Problem `type` URIs live in the ecosystem's identifier namespace. They are identifiers, never fetched. */
96
+ export const PROBLEM_TYPE_BASE = "https://kashscript.com/indorania/problems/";
97
+ export const PROBLEMS = {
98
+ invalid_request: { status: 400, title: "The request does not match the contract" },
99
+ version_required: { status: 400, title: "Say which API version you speak" },
100
+ version_unknown: { status: 400, title: "That API version does not exist" },
101
+ idempotency_key_required: { status: 400, title: "A change needs an Idempotency-Key" },
102
+ idempotency_key_invalid: { status: 400, title: "The Idempotency-Key is not well formed" },
103
+ unauthenticated: { status: 401, title: "Say who is calling" },
104
+ signature_invalid: { status: 401, title: "The signature does not verify" },
105
+ forbidden: { status: 403, title: "Not allowed for this caller" },
106
+ not_found: { status: 404, title: "Nothing is here" },
107
+ idempotency_in_progress: { status: 409, title: "A request with this Idempotency-Key is still running" },
108
+ version_conflict: { status: 412, title: "It changed since you last read it" },
109
+ idempotency_key_reused: { status: 422, title: "This Idempotency-Key was used for a different request" },
110
+ internal: { status: 500, title: "Something failed on our side" },
111
+ not_built: { status: 501, title: "In the contract, not built yet" },
112
+ };
113
+ export const ProblemDetail = z
114
+ .object({
115
+ path: z.string(),
116
+ message: z.string(),
117
+ rule: z.string().optional().meta({ description: "The rule broken, when a published rule names it — e.g. an ask's `R8-no-improvement-item`." }),
118
+ })
119
+ .strict();
120
+ export const Problem = z
121
+ .object({
122
+ type: z.string().meta({ description: `${PROBLEM_TYPE_BASE}<code>` }),
123
+ title: z.string(),
124
+ status: z.number().int().min(400).max(599),
125
+ code: z.string().regex(/^[a-z][a-z0-9_]*$/).meta({ description: "Stable and machine-readable. New codes may appear inside a version; treat an unknown code by its status." }),
126
+ detail: z.string().optional(),
127
+ instance: z.string().optional().meta({ description: "urn:uuid:<request id>" }),
128
+ errors: z.array(ProblemDetail).optional(),
129
+ })
130
+ .meta({
131
+ id: "Problem",
132
+ description: "The one error envelope: RFC 9457 problem details, served as application/problem+json, with a stable `code`.",
133
+ });
134
+ export function problem(code, init = {}) {
135
+ const { status, title } = PROBLEMS[code];
136
+ return {
137
+ type: PROBLEM_TYPE_BASE + code,
138
+ title,
139
+ status,
140
+ code,
141
+ ...(init.detail === undefined ? {} : { detail: init.detail }),
142
+ ...(init.instance === undefined ? {} : { instance: init.instance }),
143
+ ...(init.errors === undefined ? {} : { errors: init.errors }),
144
+ };
145
+ }
146
+ // ── Pages ──────────────────────────────────────────────────────────────────────────────────────
147
+ export const PageQuery = z
148
+ .object({
149
+ cursor: z.string().max(256).optional().meta({ description: "From the previous page's `next`." }),
150
+ limit: z.coerce.number().int().min(1).max(100).optional().meta({ description: "At most 100; 20 when absent." }),
151
+ })
152
+ .strict();
153
+ export function pageOf(item, id) {
154
+ return z
155
+ .object({
156
+ items: z.array(item),
157
+ next: z.string().nullable().meta({ description: "An opaque cursor for the next page, or null at the end." }),
158
+ })
159
+ .strict()
160
+ .meta({ id });
161
+ }
162
+ //# sourceMappingURL=common.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"common.js","sourceRoot":"","sources":["../src/common.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * `@indorania/contracts/constitution` — the constitution as checks, not trust (PLATFORM-SESSIONS
3
+ * ground rules). The same checks run in this repository's CI and can run in any member's.
4
+ */
5
+ export { checkOpenApi, COLLECTIONS, PERSON_SIDE_SCHEMA, type OpenApiCheckOptions } from "./openapi.ts";
6
+ export { checkTables, EXPIRY_COLUMN, type AcceptedColumn, type ColumnModel, type DbModel, type ForeignKeyModel, type JsonColumnClass, type TableModel } from "./tables.ts";
7
+ export { RULES, formatReport, passed, summarise, type AcceptedFinding, type Finding, type RuleId, type RuleResult } from "./report.ts";
8
+ export { BIRTH_OR_ORIGIN, DECLINE_TOKENS, MEMBER_NAME_PATTERN, MEMBER_NAMES, MEMBERSHIP_TOKENS, METER_TOKENS, ORIGIN_TOKENS, PERSON_TOKENS, SCORE_TOKENS, SECRET_TOKENS, hasToken, tokens, } from "./words.ts";
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/constitution/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAAE,KAAK,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACvG,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,KAAK,cAAc,EAAE,KAAK,WAAW,EAAE,KAAK,OAAO,EAAE,KAAK,eAAe,EAAE,KAAK,eAAe,EAAE,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AAC3K,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,eAAe,EAAE,KAAK,OAAO,EAAE,KAAK,MAAM,EAAE,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AACvI,OAAO,EACL,eAAe,EACf,cAAc,EACd,mBAAmB,EACnB,YAAY,EACZ,iBAAiB,EACjB,YAAY,EACZ,aAAa,EACb,aAAa,EACb,YAAY,EACZ,aAAa,EACb,QAAQ,EACR,MAAM,GACP,MAAM,YAAY,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * `@indorania/contracts/constitution` — the constitution as checks, not trust (PLATFORM-SESSIONS
3
+ * ground rules). The same checks run in this repository's CI and can run in any member's.
4
+ */
5
+ export { checkOpenApi, COLLECTIONS, PERSON_SIDE_SCHEMA } from "./openapi.js";
6
+ export { checkTables, EXPIRY_COLUMN } from "./tables.js";
7
+ export { RULES, formatReport, passed, summarise } from "./report.js";
8
+ export { BIRTH_OR_ORIGIN, DECLINE_TOKENS, MEMBER_NAME_PATTERN, MEMBER_NAMES, MEMBERSHIP_TOKENS, METER_TOKENS, ORIGIN_TOKENS, PERSON_TOKENS, SCORE_TOKENS, SECRET_TOKENS, hasToken, tokens, } from "./words.js";
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/constitution/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAA4B,MAAM,cAAc,CAAC;AACvG,OAAO,EAAE,WAAW,EAAE,aAAa,EAAoH,MAAM,aAAa,CAAC;AAC3K,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,EAAE,SAAS,EAAoE,MAAM,aAAa,CAAC;AACvI,OAAO,EACL,eAAe,EACf,cAAc,EACd,mBAAmB,EACnB,YAAY,EACZ,iBAAiB,EACjB,YAAY,EACZ,aAAa,EACb,aAAa,EACb,YAAY,EACZ,aAAa,EACb,QAAQ,EACR,MAAM,GACP,MAAM,YAAY,CAAC"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * The constitution, checked against an OpenAPI 3.1 document. Pure: it reads the document and
3
+ * reports; it imports nothing from the kernel, so any member can run it on its own contract.
4
+ */
5
+ import { type RuleResult } from "./report.ts";
6
+ /** The one person-side identifier component (see `RelationshipId` in common.ts). */
7
+ export declare const PERSON_SIDE_SCHEMA = "RelationshipId";
8
+ export declare const ORGANISATION_ID_SCHEMA = "OrganisationId";
9
+ export declare const ENVELOPE_SCHEMA = "DsseEnvelope";
10
+ /**
11
+ * The only reads allowed to return a list (d41: no endpoint answers "everything matching X", for
12
+ * anyone, admin included). Each is the caller's own, or public by design; its reason is on the
13
+ * operation as `x-indorania-collection`. Adding one is a reviewed edit to this list.
14
+ */
15
+ export declare const COLLECTIONS: readonly string[];
16
+ export interface OpenApiCheckOptions {
17
+ /** Names a thank-you may never carry at any depth — attest's `FORBIDDEN_VOUCHER_FIELDS` (d49). */
18
+ readonly voucherFields?: readonly string[];
19
+ /** Defaults to `COLLECTIONS`. */
20
+ readonly collections?: readonly string[];
21
+ }
22
+ export declare function checkOpenApi(document: object, options?: OpenApiCheckOptions): RuleResult[];
23
+ //# sourceMappingURL=openapi.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openapi.d.ts","sourceRoot":"","sources":["../../src/constitution/openapi.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAwC,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AAgBpF,oFAAoF;AACpF,eAAO,MAAM,kBAAkB,mBAAmB,CAAC;AACnD,eAAO,MAAM,sBAAsB,mBAAmB,CAAC;AACvD,eAAO,MAAM,eAAe,iBAAiB,CAAC;AAE9C;;;;GAIG;AACH,eAAO,MAAM,WAAW,EAAE,SAAS,MAAM,EASxC,CAAC;AAMF,MAAM,WAAW,mBAAmB;IAClC,kGAAkG;IAClG,QAAQ,CAAC,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3C,iCAAiC;IACjC,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC1C;AAiND,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,mBAAwB,GAAG,UAAU,EAAE,CA+H9F"}