@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.
- package/README.md +117 -0
- package/dist/common.d.ts +144 -0
- package/dist/common.d.ts.map +1 -0
- package/dist/common.js +162 -0
- package/dist/common.js.map +1 -0
- package/dist/constitution/index.d.ts +9 -0
- package/dist/constitution/index.d.ts.map +1 -0
- package/dist/constitution/index.js +9 -0
- package/dist/constitution/index.js.map +1 -0
- package/dist/constitution/openapi.d.ts +23 -0
- package/dist/constitution/openapi.d.ts.map +1 -0
- package/dist/constitution/openapi.js +375 -0
- package/dist/constitution/openapi.js.map +1 -0
- package/dist/constitution/report.d.ts +63 -0
- package/dist/constitution/report.d.ts.map +1 -0
- package/dist/constitution/report.js +73 -0
- package/dist/constitution/report.js.map +1 -0
- package/dist/constitution/tables.d.ts +53 -0
- package/dist/constitution/tables.d.ts.map +1 -0
- package/dist/constitution/tables.js +96 -0
- package/dist/constitution/tables.js.map +1 -0
- package/dist/constitution/words.d.ts +39 -0
- package/dist/constitution/words.d.ts.map +1 -0
- package/dist/constitution/words.js +126 -0
- package/dist/constitution/words.js.map +1 -0
- package/dist/document.d.ts +12 -0
- package/dist/document.d.ts.map +1 -0
- package/dist/document.js +106 -0
- package/dist/document.js.map +1 -0
- package/dist/domain-error.d.ts +14 -0
- package/dist/domain-error.d.ts.map +1 -0
- package/dist/domain-error.js +23 -0
- package/dist/domain-error.js.map +1 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +24 -0
- package/dist/index.js.map +1 -0
- package/dist/op.d.ts +92 -0
- package/dist/op.d.ts.map +1 -0
- package/dist/op.js +113 -0
- package/dist/op.js.map +1 -0
- package/dist/routes/asks.d.ts +77 -0
- package/dist/routes/asks.d.ts.map +1 -0
- package/dist/routes/asks.js +182 -0
- package/dist/routes/asks.js.map +1 -0
- package/dist/routes/backup.d.ts +12 -0
- package/dist/routes/backup.d.ts.map +1 -0
- package/dist/routes/backup.js +63 -0
- package/dist/routes/backup.js.map +1 -0
- package/dist/routes/capabilities.d.ts +67 -0
- package/dist/routes/capabilities.d.ts.map +1 -0
- package/dist/routes/capabilities.js +88 -0
- package/dist/routes/capabilities.js.map +1 -0
- package/dist/routes/entitlements.d.ts +137 -0
- package/dist/routes/entitlements.d.ts.map +1 -0
- package/dist/routes/entitlements.js +101 -0
- package/dist/routes/entitlements.js.map +1 -0
- package/dist/routes/guest.d.ts +57 -0
- package/dist/routes/guest.d.ts.map +1 -0
- package/dist/routes/guest.js +140 -0
- package/dist/routes/guest.js.map +1 -0
- package/dist/routes/integration.d.ts +187 -0
- package/dist/routes/integration.d.ts.map +1 -0
- package/dist/routes/integration.js +243 -0
- package/dist/routes/integration.js.map +1 -0
- package/dist/routes/meta.d.ts +50 -0
- package/dist/routes/meta.d.ts.map +1 -0
- package/dist/routes/meta.js +90 -0
- package/dist/routes/meta.js.map +1 -0
- package/dist/routes/organisations.d.ts +121 -0
- package/dist/routes/organisations.d.ts.map +1 -0
- package/dist/routes/organisations.js +175 -0
- package/dist/routes/organisations.js.map +1 -0
- package/dist/routes/presentations.d.ts +95 -0
- package/dist/routes/presentations.d.ts.map +1 -0
- package/dist/routes/presentations.js +121 -0
- package/dist/routes/presentations.js.map +1 -0
- package/dist/routes/sessions.d.ts +180 -0
- package/dist/routes/sessions.d.ts.map +1 -0
- package/dist/routes/sessions.js +240 -0
- package/dist/routes/sessions.js.map +1 -0
- package/dist/routes/standing.d.ts +24 -0
- package/dist/routes/standing.d.ts.map +1 -0
- package/dist/routes/standing.js +74 -0
- package/dist/routes/standing.js.map +1 -0
- package/dist/routes/thank-yous.d.ts +30 -0
- package/dist/routes/thank-yous.d.ts.map +1 -0
- package/dist/routes/thank-yous.js +139 -0
- package/dist/routes/thank-yous.js.map +1 -0
- package/dist/versions.d.ts +46 -0
- package/dist/versions.d.ts.map +1 -0
- package/dist/versions.js +54 -0
- package/dist/versions.js.map +1 -0
- package/dist/webhooks.d.ts +55 -0
- package/dist/webhooks.d.ts.map +1 -0
- package/dist/webhooks.js +76 -0
- package/dist/webhooks.js.map +1 -0
- package/dist/zod.d.ts +3 -0
- package/dist/zod.d.ts.map +1 -0
- package/dist/zod.js +7 -0
- package/dist/zod.js.map +1 -0
- package/node/kernel-esm.mjs +27 -0
- package/node/register.mjs +5 -0
- package/openapi/2026-09-25.json +6959 -0
- package/openapi/versions.json +10 -0
- package/package.json +49 -0
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The session (d42 §4, d47(d)): one encounter, both signatures on every line
|
|
3
|
+
* (specs/session-receipt.md). Indorania relays lines between the two parties, anchors them, and
|
|
4
|
+
* never signs one as a party. The relay forgets a session's content after delivery and expiry, and
|
|
5
|
+
* there is no way to list sessions — each party keeps its own copy in its own book or wallet.
|
|
6
|
+
*
|
|
7
|
+
* An invitation nobody consents to is not a decline: it simply expires, and then it is gone.
|
|
8
|
+
*/
|
|
9
|
+
import { SESSION_PROFILES, SESSION_RECEIPT_FORMAT } from "@kashscript/attest/exchange";
|
|
10
|
+
import { DsseEnvelope, HttpsUrl, OrgDid, Problem, RelationshipId, SessionId, UnixTime, pageOf, words } from "../common.js";
|
|
11
|
+
import { operation } from "../op.js";
|
|
12
|
+
import { z } from "../zod.js";
|
|
13
|
+
import { AskKey } from "./asks.js";
|
|
14
|
+
const PROFILES = Object.keys(SESSION_PROFILES);
|
|
15
|
+
export const RECORD_KINDS = ["presence", "process", "flow"];
|
|
16
|
+
export const SessionProfile = z.enum(PROFILES).meta({
|
|
17
|
+
id: "SessionProfile",
|
|
18
|
+
description: "So a coffee does not record what a repair needs (d42 §4): presence+flow · process+flow · presence+process+flow · flow+process, which has no presence and no place.",
|
|
19
|
+
});
|
|
20
|
+
const Consent = z
|
|
21
|
+
.object({
|
|
22
|
+
records: z.array(z.enum(RECORD_KINDS)).min(1).meta({ description: "What the session will record. The person sees this on one screen before anything is recorded." }),
|
|
23
|
+
asks: z.array(z.object({ key: AskKey, version: z.number().int().min(1) }).strict()).max(8).meta({ description: "Asks the person may be shown during the session. Each can be answered no, at no further cost." }),
|
|
24
|
+
})
|
|
25
|
+
.strict();
|
|
26
|
+
export const SessionOpen = z
|
|
27
|
+
.object({
|
|
28
|
+
profile: SessionProfile,
|
|
29
|
+
consent: Consent,
|
|
30
|
+
place: words(120).optional().meta({ description: "A place label, only where the profile allows one." }),
|
|
31
|
+
expiresInSec: z.number().int().min(60).max(86_400).optional().meta({ description: "How long the invitation stands; minutes suit a counter." }),
|
|
32
|
+
})
|
|
33
|
+
.strict()
|
|
34
|
+
.superRefine((open, ctx) => {
|
|
35
|
+
const profile = SESSION_PROFILES[open.profile];
|
|
36
|
+
for (const kind of open.consent.records) {
|
|
37
|
+
if (!profile.kinds.includes(kind)) {
|
|
38
|
+
ctx.addIssue({ code: "custom", path: ["consent", "records"], message: `${open.profile} records no ${kind} line`, params: { rule: "PROFILE_VIOLATION" } });
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (open.place !== undefined && !profile.place) {
|
|
42
|
+
ctx.addIssue({ code: "custom", path: ["place"], message: `${open.profile} carries no place`, params: { rule: "PLACE_NOT_ALLOWED" } });
|
|
43
|
+
}
|
|
44
|
+
})
|
|
45
|
+
.meta({ id: "SessionOpen" });
|
|
46
|
+
export const SessionTerms = z
|
|
47
|
+
.object({
|
|
48
|
+
id: SessionId,
|
|
49
|
+
profile: SessionProfile,
|
|
50
|
+
consent: Consent,
|
|
51
|
+
place: words(120).nullable(),
|
|
52
|
+
establishment: OrgDid,
|
|
53
|
+
expiresAtUnix: UnixTime,
|
|
54
|
+
})
|
|
55
|
+
.strict()
|
|
56
|
+
.meta({ id: "SessionTerms", description: "What the one-screen consent shows. `establishment` is the establishment's party identifier for this session." });
|
|
57
|
+
export const SessionInvitation = SessionTerms.extend({
|
|
58
|
+
joinUri: HttpsUrl.meta({ description: "Carries the join secret. Show it as a QR code at the counter, or send it." }),
|
|
59
|
+
}).meta({ id: "SessionInvitation" });
|
|
60
|
+
export const LineWrite = z
|
|
61
|
+
.object({ line: DsseEnvelope })
|
|
62
|
+
.strict()
|
|
63
|
+
.meta({ id: "LineWrite", description: "One `application/vnd.indorania.session-event+json` line, signed by its author." });
|
|
64
|
+
export const LineAccepted = z.object({ seq: z.number().int().min(0) }).strict().meta({ id: "LineAccepted" });
|
|
65
|
+
const Signature = z.object({ keyid: z.string(), sig: z.string() }).strict();
|
|
66
|
+
export const Countersignature = z
|
|
67
|
+
.object({ signature: Signature.meta({ description: "The other party's signature over the same PAE bytes." }) })
|
|
68
|
+
.strict()
|
|
69
|
+
.meta({ id: "Countersignature" });
|
|
70
|
+
export const LineState = z.enum(["waiting", "signed-by-both"]).meta({
|
|
71
|
+
id: "LineState",
|
|
72
|
+
description: "One signature is waiting, never proof (d41: two signatures or it is not proof).",
|
|
73
|
+
});
|
|
74
|
+
export const SessionLine = z.object({ seq: z.number().int().min(0), line: DsseEnvelope, state: LineState }).strict().meta({ id: "SessionLine" });
|
|
75
|
+
export const SyncBatch = z
|
|
76
|
+
.object({
|
|
77
|
+
lines: z.array(DsseEnvelope).max(256),
|
|
78
|
+
countersignatures: z.array(z.object({ seq: z.number().int().min(0), signature: Signature }).strict()).max(256),
|
|
79
|
+
})
|
|
80
|
+
.strict()
|
|
81
|
+
.meta({ id: "SyncBatch", description: "Lines and countersignatures made while offline, in order." });
|
|
82
|
+
export const SyncResult = z
|
|
83
|
+
.object({
|
|
84
|
+
accepted: z.array(z.number().int().min(0)),
|
|
85
|
+
rejected: z.array(z.object({ seq: z.number().int().min(0), problem: Problem }).strict()),
|
|
86
|
+
})
|
|
87
|
+
.strict()
|
|
88
|
+
.meta({ id: "SyncResult" });
|
|
89
|
+
/** `kashscript-session-receipt/1`, as attest's `SessionReceipt` defines it. */
|
|
90
|
+
export const SessionReceipt = z
|
|
91
|
+
.object({
|
|
92
|
+
formatVersion: z.literal(SESSION_RECEIPT_FORMAT),
|
|
93
|
+
sessionId: SessionId,
|
|
94
|
+
profile: SessionProfile,
|
|
95
|
+
parties: z.object({ establishment: OrgDid, person: RelationshipId }).strict(),
|
|
96
|
+
events: z.array(DsseEnvelope),
|
|
97
|
+
anchor: z
|
|
98
|
+
.object({
|
|
99
|
+
headSha256: z.string().regex(/^[0-9a-f]{64}$/),
|
|
100
|
+
coversSeq: z.number().int().min(0),
|
|
101
|
+
witness: z.record(z.string(), z.unknown()),
|
|
102
|
+
})
|
|
103
|
+
.strict()
|
|
104
|
+
.nullable(),
|
|
105
|
+
})
|
|
106
|
+
.strict()
|
|
107
|
+
.meta({
|
|
108
|
+
id: "SessionReceipt",
|
|
109
|
+
description: "Both parties' record of one session. The total is shared; line items are salted hashes (d41: arrival, not consumption). Verify it with @kashscript/attest, offline.",
|
|
110
|
+
});
|
|
111
|
+
const SessionParams = z.object({ sessionId: SessionId }).strict();
|
|
112
|
+
const LineParams = z.object({ sessionId: SessionId, seq: z.coerce.number().int().min(0) }).strict();
|
|
113
|
+
const JoinSecret = z.object({ k: z.string().regex(/^[A-Za-z0-9_-]{22,64}$/).meta({ description: "The join secret from the invitation's joinUri." }) }).strict();
|
|
114
|
+
const PARTY = ["seat", "integration", "relationshipProof"];
|
|
115
|
+
export const sessionOperations = [
|
|
116
|
+
operation({
|
|
117
|
+
operationId: "openSession",
|
|
118
|
+
method: "post",
|
|
119
|
+
path: "/v1/sessions",
|
|
120
|
+
tag: "sessions",
|
|
121
|
+
summary: "Open a session: invite the person across the counter",
|
|
122
|
+
auth: ["seat", "integration"],
|
|
123
|
+
pending: "PL-8",
|
|
124
|
+
idempotency: "key",
|
|
125
|
+
body: { schema: SessionOpen },
|
|
126
|
+
responses: { 201: { description: "The invitation.", schema: SessionInvitation } },
|
|
127
|
+
}),
|
|
128
|
+
operation({
|
|
129
|
+
operationId: "getSessionInvitation",
|
|
130
|
+
method: "get",
|
|
131
|
+
path: "/v1/sessions/{sessionId}/invitation",
|
|
132
|
+
tag: "sessions",
|
|
133
|
+
summary: "What the person is asked to agree to",
|
|
134
|
+
description: "Needs only the join secret. Reading it records nothing.",
|
|
135
|
+
auth: [],
|
|
136
|
+
pending: "PL-8",
|
|
137
|
+
params: SessionParams,
|
|
138
|
+
query: JoinSecret,
|
|
139
|
+
responses: { 200: { description: "The terms for the one-screen consent.", schema: SessionTerms } },
|
|
140
|
+
}),
|
|
141
|
+
operation({
|
|
142
|
+
operationId: "consentToSession",
|
|
143
|
+
method: "post",
|
|
144
|
+
path: "/v1/sessions/{sessionId}/consent",
|
|
145
|
+
tag: "sessions",
|
|
146
|
+
summary: "Consent: the person's signed open line",
|
|
147
|
+
description: "The person's yes is the session's first line, which they sign. There is no endpoint for a no: nothing is sent, and the invitation expires.",
|
|
148
|
+
auth: ["relationshipProof"],
|
|
149
|
+
pending: "PL-8",
|
|
150
|
+
idempotency: "key",
|
|
151
|
+
params: SessionParams,
|
|
152
|
+
query: JoinSecret,
|
|
153
|
+
body: { schema: LineWrite },
|
|
154
|
+
responses: { 201: { description: "The open line, waiting for the establishment's signature.", schema: LineAccepted } },
|
|
155
|
+
}),
|
|
156
|
+
operation({
|
|
157
|
+
operationId: "appendSessionLine",
|
|
158
|
+
method: "post",
|
|
159
|
+
path: "/v1/sessions/{sessionId}/lines",
|
|
160
|
+
tag: "sessions",
|
|
161
|
+
summary: "Add a line: presence, flow, process or disagreement",
|
|
162
|
+
description: "Signed by its author. A disagreement is a new line naming the one it disputes, never an edit.",
|
|
163
|
+
auth: PARTY,
|
|
164
|
+
pending: "PL-8",
|
|
165
|
+
idempotency: "key",
|
|
166
|
+
params: SessionParams,
|
|
167
|
+
body: { schema: LineWrite },
|
|
168
|
+
responses: { 201: { description: "Added, waiting for the other party.", schema: LineAccepted } },
|
|
169
|
+
}),
|
|
170
|
+
operation({
|
|
171
|
+
operationId: "countersignSessionLine",
|
|
172
|
+
method: "post",
|
|
173
|
+
path: "/v1/sessions/{sessionId}/lines/{seq}/countersignature",
|
|
174
|
+
tag: "sessions",
|
|
175
|
+
summary: "Countersign the other party's line",
|
|
176
|
+
auth: PARTY,
|
|
177
|
+
pending: "PL-8",
|
|
178
|
+
idempotency: "key",
|
|
179
|
+
params: LineParams,
|
|
180
|
+
body: { schema: Countersignature },
|
|
181
|
+
responses: { 200: { description: "Signed by both.", schema: SessionLine } },
|
|
182
|
+
}),
|
|
183
|
+
operation({
|
|
184
|
+
operationId: "closeSession",
|
|
185
|
+
method: "post",
|
|
186
|
+
path: "/v1/sessions/{sessionId}/close",
|
|
187
|
+
tag: "sessions",
|
|
188
|
+
summary: "Close the session with its shared total",
|
|
189
|
+
description: "Either side may close; neither may delete. Disagreements may still follow the close.",
|
|
190
|
+
auth: PARTY,
|
|
191
|
+
pending: "PL-8",
|
|
192
|
+
idempotency: "key",
|
|
193
|
+
params: SessionParams,
|
|
194
|
+
body: { schema: LineWrite },
|
|
195
|
+
responses: { 201: { description: "The close line, waiting for the other party.", schema: LineAccepted } },
|
|
196
|
+
}),
|
|
197
|
+
operation({
|
|
198
|
+
operationId: "listSessionLines",
|
|
199
|
+
method: "get",
|
|
200
|
+
path: "/v1/sessions/{sessionId}/lines",
|
|
201
|
+
tag: "sessions",
|
|
202
|
+
summary: "The lines of one session, after a point (sync down)",
|
|
203
|
+
auth: PARTY,
|
|
204
|
+
pending: "PL-8",
|
|
205
|
+
collection: "The lines of one session, for its two parties only: one relationship, never a search.",
|
|
206
|
+
params: SessionParams,
|
|
207
|
+
query: z
|
|
208
|
+
.object({
|
|
209
|
+
after: z.coerce.number().int().min(-1).optional().meta({ description: "The last seq you hold; -1 or absent for all." }),
|
|
210
|
+
limit: z.coerce.number().int().min(1).max(256).optional(),
|
|
211
|
+
})
|
|
212
|
+
.strict(),
|
|
213
|
+
responses: { 200: { description: "One page of lines.", schema: pageOf(SessionLine, "SessionLinePage") } },
|
|
214
|
+
}),
|
|
215
|
+
operation({
|
|
216
|
+
operationId: "syncSession",
|
|
217
|
+
method: "post",
|
|
218
|
+
path: "/v1/sessions/{sessionId}/sync",
|
|
219
|
+
tag: "sessions",
|
|
220
|
+
summary: "Upload what was signed offline (sync up)",
|
|
221
|
+
auth: PARTY,
|
|
222
|
+
pending: "PL-8",
|
|
223
|
+
idempotency: "key",
|
|
224
|
+
params: SessionParams,
|
|
225
|
+
body: { schema: SyncBatch },
|
|
226
|
+
responses: { 200: { description: "What was accepted, and why anything was not.", schema: SyncResult } },
|
|
227
|
+
}),
|
|
228
|
+
operation({
|
|
229
|
+
operationId: "getSessionReceipt",
|
|
230
|
+
method: "get",
|
|
231
|
+
path: "/v1/sessions/{sessionId}/receipt",
|
|
232
|
+
tag: "sessions",
|
|
233
|
+
summary: "The session receipt, for either party",
|
|
234
|
+
auth: PARTY,
|
|
235
|
+
pending: "PL-8",
|
|
236
|
+
params: SessionParams,
|
|
237
|
+
responses: { 200: { description: "The receipt: pending until every line carries both signatures and the session is closed.", schema: SessionReceipt } },
|
|
238
|
+
}),
|
|
239
|
+
];
|
|
240
|
+
//# sourceMappingURL=sessions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessions.js","sourceRoot":"","sources":["../../src/routes/sessions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { z } from "../zod.ts";
|
|
2
|
+
export declare const StandingRule: z.ZodObject<{
|
|
3
|
+
id: z.ZodString;
|
|
4
|
+
version: z.ZodString;
|
|
5
|
+
title: z.ZodString;
|
|
6
|
+
needs: z.ZodArray<z.ZodObject<{
|
|
7
|
+
predicate: z.ZodString;
|
|
8
|
+
withinDays: z.ZodNumber;
|
|
9
|
+
}, z.core.$strict>>;
|
|
10
|
+
validForDays: z.ZodNumber;
|
|
11
|
+
}, z.core.$strict>;
|
|
12
|
+
export declare const StandingRequest: z.ZodObject<{
|
|
13
|
+
rule: z.ZodObject<{
|
|
14
|
+
id: z.ZodString;
|
|
15
|
+
version: z.ZodString;
|
|
16
|
+
}, z.core.$strict>;
|
|
17
|
+
vpToken: z.ZodString;
|
|
18
|
+
}, z.core.$strict>;
|
|
19
|
+
export declare const StandingCredential: z.ZodObject<{
|
|
20
|
+
credential: z.ZodString;
|
|
21
|
+
expiresAtUnix: z.ZodNumber;
|
|
22
|
+
}, z.core.$strict>;
|
|
23
|
+
export declare const standingOperations: import("../op.ts").Operation[];
|
|
24
|
+
//# sourceMappingURL=standing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"standing.d.ts","sourceRoot":"","sources":["../../src/routes/standing.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,CAAC,EAAE,MAAM,WAAW,CAAC;AAe9B,eAAO,MAAM,YAAY;;;;;;;;;kBAW4F,CAAC;AAEtH,eAAO,MAAM,eAAe;;;;;;kBAMM,CAAC;AAEnC,eAAO,MAAM,kBAAkB;;;kBAMM,CAAC;AAEtC,eAAO,MAAM,kBAAkB,gCA0B9B,CAAC"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Standing (d42 §2, d47(d)): derived on request from presented predicates, signed, expiring — and
|
|
3
|
+
* nothing that links is kept, so there is no way to list or look up a past request. The rules are
|
|
4
|
+
* published; other issuers may derive standing under them, and verifiers choose whom to trust.
|
|
5
|
+
*/
|
|
6
|
+
import { FORBIDDEN_NEED_PATTERN, PREDICATE_KIND_PATTERN } from "@kashscript/attest/exchange";
|
|
7
|
+
import { UnixTime, pageOf, PageQuery, words } from "../common.js";
|
|
8
|
+
import { operation } from "../op.js";
|
|
9
|
+
import { z } from "../zod.js";
|
|
10
|
+
const forbidden = new RegExp(FORBIDDEN_NEED_PATTERN, "i");
|
|
11
|
+
/**
|
|
12
|
+
* A standing item may rest on the improvement item — "improved the way this work is done" is itself
|
|
13
|
+
* a standing item, issued only on the holder's request (d43) — so, unlike an ask's need, it is not
|
|
14
|
+
* refused here. It is never requirable by an ask; `PredicateKind` enforces that side.
|
|
15
|
+
*/
|
|
16
|
+
const StandingPredicate = z
|
|
17
|
+
.string()
|
|
18
|
+
.regex(new RegExp(PREDICATE_KIND_PATTERN))
|
|
19
|
+
.refine((k) => !forbidden.test(k), { message: "nothing refers to origin, ethnicity, sect, caste or ancestry (d36)", params: { rule: "FORBIDDEN-NEED" } })
|
|
20
|
+
.meta({ not: { pattern: FORBIDDEN_NEED_PATTERN } });
|
|
21
|
+
export const StandingRule = z
|
|
22
|
+
.object({
|
|
23
|
+
id: z.string().regex(/^standing:[a-z0-9]+(-[a-z0-9]+)*$/),
|
|
24
|
+
version: z.string().min(1),
|
|
25
|
+
title: words(120),
|
|
26
|
+
needs: z
|
|
27
|
+
.array(z.object({ predicate: StandingPredicate, withinDays: z.number().int().min(1) }).strict())
|
|
28
|
+
.min(1),
|
|
29
|
+
validForDays: z.number().int().min(1).max(366).meta({ description: "Standing expires. A permanent badge is a score with better manners (d42 §2)." }),
|
|
30
|
+
})
|
|
31
|
+
.strict()
|
|
32
|
+
.meta({ id: "StandingRule", description: "One published standing rule: what it rests on, and how long it holds." });
|
|
33
|
+
export const StandingRequest = z
|
|
34
|
+
.object({
|
|
35
|
+
rule: z.object({ id: z.string(), version: z.string() }).strict(),
|
|
36
|
+
vpToken: z.string().min(1).meta({ description: "The holder's presentations, each bound to their relationship key with this issuer." }),
|
|
37
|
+
})
|
|
38
|
+
.strict()
|
|
39
|
+
.meta({ id: "StandingRequest" });
|
|
40
|
+
export const StandingCredential = z
|
|
41
|
+
.object({
|
|
42
|
+
credential: z.string().min(1).meta({ description: "A holder-bound SD-JWT VC. Its type is registered when PL-8 builds it." }),
|
|
43
|
+
expiresAtUnix: UnixTime,
|
|
44
|
+
})
|
|
45
|
+
.strict()
|
|
46
|
+
.meta({ id: "StandingCredential" });
|
|
47
|
+
export const standingOperations = [
|
|
48
|
+
operation({
|
|
49
|
+
operationId: "listStandingRules",
|
|
50
|
+
method: "get",
|
|
51
|
+
path: "/v1/standing/rules",
|
|
52
|
+
tag: "standing",
|
|
53
|
+
summary: "The published standing rules",
|
|
54
|
+
auth: [],
|
|
55
|
+
pending: "PL-8",
|
|
56
|
+
collection: "The standing rules are published, so anyone can re-implement or check them (d47(d)).",
|
|
57
|
+
query: PageQuery,
|
|
58
|
+
responses: { 200: { description: "One page of rules.", schema: pageOf(StandingRule, "StandingRulePage") } },
|
|
59
|
+
}),
|
|
60
|
+
operation({
|
|
61
|
+
operationId: "requestStanding",
|
|
62
|
+
method: "post",
|
|
63
|
+
path: "/v1/standing/requests",
|
|
64
|
+
tag: "standing",
|
|
65
|
+
summary: "Derive standing from presented predicates",
|
|
66
|
+
description: "Answered at once, and forgotten: no request is stored, so none can be listed or looked up.",
|
|
67
|
+
auth: ["relationshipProof"],
|
|
68
|
+
pending: "PL-8",
|
|
69
|
+
idempotency: "key",
|
|
70
|
+
body: { schema: StandingRequest },
|
|
71
|
+
responses: { 201: { description: "The standing credential.", schema: StandingCredential } },
|
|
72
|
+
}),
|
|
73
|
+
];
|
|
74
|
+
//# sourceMappingURL=standing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"standing.js","sourceRoot":"","sources":["../../src/routes/standing.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { z } from "../zod.ts";
|
|
2
|
+
export declare const ThankYouFor: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
3
|
+
act: z.ZodLiteral<"confirmed-session">;
|
|
4
|
+
session: z.ZodString;
|
|
5
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
6
|
+
act: z.ZodLiteral<"answered-ask">;
|
|
7
|
+
presentationRequest: z.ZodString;
|
|
8
|
+
}, z.core.$strict>], "act">;
|
|
9
|
+
export declare const ThankYouIssue: z.ZodObject<{
|
|
10
|
+
for: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
11
|
+
act: z.ZodLiteral<"confirmed-session">;
|
|
12
|
+
session: z.ZodString;
|
|
13
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
14
|
+
act: z.ZodLiteral<"answered-ask">;
|
|
15
|
+
presentationRequest: z.ZodString;
|
|
16
|
+
}, z.core.$strict>], "act">;
|
|
17
|
+
value: z.ZodString;
|
|
18
|
+
redeemAt: z.ZodString;
|
|
19
|
+
expiresAtUnix: z.ZodNumber;
|
|
20
|
+
}, z.core.$strict>;
|
|
21
|
+
export declare const ThankYouOffer: z.ZodObject<{
|
|
22
|
+
id: z.ZodString;
|
|
23
|
+
offer: z.ZodObject<{
|
|
24
|
+
uri: z.ZodString;
|
|
25
|
+
url: z.ZodURL;
|
|
26
|
+
}, z.core.$strict>;
|
|
27
|
+
expiresAtUnix: z.ZodNumber;
|
|
28
|
+
}, z.core.$strict>;
|
|
29
|
+
export declare const thankYouOperations: import("../op.ts").Operation[];
|
|
30
|
+
//# sourceMappingURL=thank-yous.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"thank-yous.d.ts","sourceRoot":"","sources":["../../src/routes/thank-yous.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,CAAC,EAAE,MAAM,WAAW,CAAC;AAE9B,eAAO,MAAM,WAAW;;;;;;2BAQpB,CAAC;AAEL,eAAO,MAAM,aAAa;;;;;;;;;;;kBAYtB,CAAC;AAEL,eAAO,MAAM,aAAa;;;;;;;kBAYwF,CAAC;AAInH,eAAO,MAAM,kBAAkB,gCA2F9B,CAAC"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The thank-you (d49(b); specs/thank-you.md): with proof on, the counterparty — never Indorania or
|
|
3
|
+
* a member — may give the person a non-transferable voucher. A promise, never a balance: its value
|
|
4
|
+
* is text, nothing adds up, and it is redeemed only with its issuer.
|
|
5
|
+
*
|
|
6
|
+
* Issue: here. Claim: OpenID for Verifiable Credential Issuance 1.0, at the issuance endpoints
|
|
7
|
+
* below. Redeem: a presentation request with the purpose `redemption`.
|
|
8
|
+
*/
|
|
9
|
+
import { HttpsUrl, PresentationRequestId, SessionId, ThankYouId, UnixTime, words } from "../common.js";
|
|
10
|
+
import { operation } from "../op.js";
|
|
11
|
+
import { z } from "../zod.js";
|
|
12
|
+
export const ThankYouFor = z
|
|
13
|
+
.discriminatedUnion("act", [
|
|
14
|
+
z.object({ act: z.literal("confirmed-session"), session: SessionId }).strict().meta({ description: "A session both parties signed, and closed." }),
|
|
15
|
+
z.object({ act: z.literal("answered-ask"), presentationRequest: PresentationRequestId }).strict().meta({ description: "Your presentation request, answered." }),
|
|
16
|
+
])
|
|
17
|
+
.meta({
|
|
18
|
+
id: "ThankYouFor",
|
|
19
|
+
description: "The answering, never the answer (d49 rule 1): confirming and disputing earn the same. The platform finds the person from the session or the request; you never name them.",
|
|
20
|
+
});
|
|
21
|
+
export const ThankYouIssue = z
|
|
22
|
+
.object({
|
|
23
|
+
for: ThankYouFor,
|
|
24
|
+
value: words(140).meta({ description: "What it is worth, as text: \"a free cup of tea on your next visit\". Never a number to add up." }),
|
|
25
|
+
redeemAt: words(140).meta({ description: "Where it is redeemed, in plain words or your own address." }),
|
|
26
|
+
expiresAtUnix: UnixTime,
|
|
27
|
+
})
|
|
28
|
+
.strict()
|
|
29
|
+
.meta({
|
|
30
|
+
id: "ThankYouIssue",
|
|
31
|
+
description: "Refused, and nothing is recorded, when the giver holds power over the person and could see who declined (d49 rule 6); when the session is not complete, or the record is device-asserted (rule 5); or past the cap per relationship per period.",
|
|
32
|
+
});
|
|
33
|
+
export const ThankYouOffer = z
|
|
34
|
+
.object({
|
|
35
|
+
id: ThankYouId,
|
|
36
|
+
offer: z
|
|
37
|
+
.object({
|
|
38
|
+
uri: z.string().regex(/^openid-credential-offer:\/\//).meta({ description: "The credential offer as a deep link, for a QR code." }),
|
|
39
|
+
url: HttpsUrl.meta({ description: "The same offer as an https link, for a message." }),
|
|
40
|
+
})
|
|
41
|
+
.strict(),
|
|
42
|
+
expiresAtUnix: UnixTime,
|
|
43
|
+
})
|
|
44
|
+
.strict()
|
|
45
|
+
.meta({ id: "ThankYouOffer", description: "Single-use, and it expires. The person claims it in their wallet." });
|
|
46
|
+
const Json = z.record(z.string(), z.unknown());
|
|
47
|
+
export const thankYouOperations = [
|
|
48
|
+
operation({
|
|
49
|
+
operationId: "issueThankYou",
|
|
50
|
+
method: "post",
|
|
51
|
+
path: "/v1/thank-yous",
|
|
52
|
+
tag: "thank-yous",
|
|
53
|
+
summary: "Give a thank-you to someone who answered",
|
|
54
|
+
auth: ["seat", "integration"],
|
|
55
|
+
pending: "PL-8",
|
|
56
|
+
idempotency: "key",
|
|
57
|
+
body: { schema: ThankYouIssue },
|
|
58
|
+
responses: { 201: { description: "An offer the person claims in their wallet.", schema: ThankYouOffer } },
|
|
59
|
+
}),
|
|
60
|
+
operation({
|
|
61
|
+
operationId: "getCredentialIssuerMetadata",
|
|
62
|
+
method: "get",
|
|
63
|
+
path: "/.well-known/openid-credential-issuer/v1/issuance",
|
|
64
|
+
tag: "issuance",
|
|
65
|
+
summary: "Credential Issuer Metadata (OpenID4VCI 1.0 §12.2)",
|
|
66
|
+
auth: [],
|
|
67
|
+
pending: "PL-8",
|
|
68
|
+
versioning: "exempt",
|
|
69
|
+
responses: { 200: { description: "The metadata, as the standard defines it.", schema: Json } },
|
|
70
|
+
}),
|
|
71
|
+
operation({
|
|
72
|
+
operationId: "getAuthorizationServerMetadata",
|
|
73
|
+
method: "get",
|
|
74
|
+
path: "/.well-known/oauth-authorization-server/v1/issuance",
|
|
75
|
+
tag: "issuance",
|
|
76
|
+
summary: "Authorization Server Metadata (RFC 8414), for the pre-authorized code flow",
|
|
77
|
+
auth: [],
|
|
78
|
+
pending: "PL-8",
|
|
79
|
+
versioning: "exempt",
|
|
80
|
+
responses: { 200: { description: "The metadata, as the standard defines it.", schema: Json } },
|
|
81
|
+
}),
|
|
82
|
+
operation({
|
|
83
|
+
operationId: "issuanceToken",
|
|
84
|
+
method: "post",
|
|
85
|
+
path: "/v1/issuance/token",
|
|
86
|
+
tag: "issuance",
|
|
87
|
+
summary: "Redeem a pre-authorized code (OpenID4VCI 1.0 §6)",
|
|
88
|
+
description: "Anonymous: no wallet client_id is ever sent (holder contract §1). The code is single-use.",
|
|
89
|
+
auth: [],
|
|
90
|
+
pending: "PL-8",
|
|
91
|
+
versioning: "exempt",
|
|
92
|
+
idempotency: "protocol",
|
|
93
|
+
body: {
|
|
94
|
+
type: "application/x-www-form-urlencoded",
|
|
95
|
+
schema: z
|
|
96
|
+
.object({
|
|
97
|
+
grant_type: z.literal("urn:ietf:params:oauth:grant-type:pre-authorized_code"),
|
|
98
|
+
"pre-authorized_code": z.string().min(1),
|
|
99
|
+
tx_code: z.string().optional(),
|
|
100
|
+
})
|
|
101
|
+
.strict(),
|
|
102
|
+
},
|
|
103
|
+
responses: { 200: { description: "An access token for the credential endpoint.", schema: Json } },
|
|
104
|
+
}),
|
|
105
|
+
operation({
|
|
106
|
+
operationId: "issuanceNonce",
|
|
107
|
+
method: "post",
|
|
108
|
+
path: "/v1/issuance/nonce",
|
|
109
|
+
tag: "issuance",
|
|
110
|
+
summary: "A fresh nonce for the key proof (OpenID4VCI 1.0 §7)",
|
|
111
|
+
auth: [],
|
|
112
|
+
pending: "PL-8",
|
|
113
|
+
versioning: "exempt",
|
|
114
|
+
idempotency: "protocol",
|
|
115
|
+
responses: { 200: { description: "{ c_nonce }", schema: z.object({ c_nonce: z.string() }).strict() } },
|
|
116
|
+
}),
|
|
117
|
+
operation({
|
|
118
|
+
operationId: "issueCredential",
|
|
119
|
+
method: "post",
|
|
120
|
+
path: "/v1/issuance/credential",
|
|
121
|
+
tag: "issuance",
|
|
122
|
+
summary: "Claim the credential (OpenID4VCI 1.0 §8)",
|
|
123
|
+
description: "The key proof is signed by the holder's relationship key for this issuer — never a global identifier.",
|
|
124
|
+
auth: ["issuanceToken"],
|
|
125
|
+
pending: "PL-8",
|
|
126
|
+
versioning: "exempt",
|
|
127
|
+
idempotency: "protocol",
|
|
128
|
+
body: {
|
|
129
|
+
schema: z
|
|
130
|
+
.object({
|
|
131
|
+
credential_configuration_id: z.string().min(1),
|
|
132
|
+
proofs: z.object({ jwt: z.array(z.string().min(1)).min(1) }).strict(),
|
|
133
|
+
})
|
|
134
|
+
.strict(),
|
|
135
|
+
},
|
|
136
|
+
responses: { 200: { description: "{ credentials: [{ credential }] }", schema: z.object({ credentials: z.array(z.object({ credential: z.string() }).strict()) }).strict() } },
|
|
137
|
+
}),
|
|
138
|
+
];
|
|
139
|
+
//# sourceMappingURL=thank-yous.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"thank-yous.js","sourceRoot":"","sources":["../../src/routes/thank-yous.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dated API versions — the Stripe pattern (ECOSYSTEM d47(h): "platform API versioning").
|
|
3
|
+
*
|
|
4
|
+
* - The URL carries the major (`/v1`, architecture §10); the header `Indorania-Version: YYYY-MM-DD`
|
|
5
|
+
* carries the dated version. Resolution: the header, else the caller's pinned version (an
|
|
6
|
+
* organisation's or an integration's), else `400 version_required`.
|
|
7
|
+
* - Every organisation and every integration is pinned to one version. Webhooks reach a receiver
|
|
8
|
+
* rendered in its pin.
|
|
9
|
+
* - A version is a **preview** until it is released — the founder publishes `@indorania/contracts`,
|
|
10
|
+
* or a member first vendors its OpenAPI file (founder decision, PL-4, 2026-09-25). Until then it
|
|
11
|
+
* may be corrected in place. Once released, it changes by addition only; anything else is a new
|
|
12
|
+
* dated version whose `changes` translate between the two.
|
|
13
|
+
* - The handlers speak the latest version. Requests travel **up** through every change after the
|
|
14
|
+
* caller's version, oldest first; responses and webhook payloads travel **down**, newest first.
|
|
15
|
+
*/
|
|
16
|
+
export type VersionStatus = "preview" | "released";
|
|
17
|
+
export interface VersionChange {
|
|
18
|
+
/** One plain sentence for the change log. */
|
|
19
|
+
readonly description: string;
|
|
20
|
+
/** A request body written for the previous version, rewritten for this one. */
|
|
21
|
+
readonly up?: (operationId: string, body: unknown) => unknown;
|
|
22
|
+
/** A response body in this version's shape, rewritten for the previous version. */
|
|
23
|
+
readonly down?: (operationId: string, status: number, body: unknown) => unknown;
|
|
24
|
+
/** A webhook payload's `data` in this version's shape, rewritten for the previous version. */
|
|
25
|
+
readonly downEvent?: (type: string, data: unknown) => unknown;
|
|
26
|
+
}
|
|
27
|
+
export interface ApiVersion {
|
|
28
|
+
/** `YYYY-MM-DD`. */
|
|
29
|
+
readonly id: string;
|
|
30
|
+
readonly status: VersionStatus;
|
|
31
|
+
/** What changed since the previous version. Empty for the first. */
|
|
32
|
+
readonly changes: readonly VersionChange[];
|
|
33
|
+
}
|
|
34
|
+
export declare const VERSION_HEADER = "indorania-version";
|
|
35
|
+
export declare const VERSION_PATTERN = "^\\d{4}-\\d{2}-\\d{2}$";
|
|
36
|
+
/** Oldest first. The last entry is the version the handlers speak. */
|
|
37
|
+
export declare const VERSIONS: readonly ApiVersion[];
|
|
38
|
+
export declare function latestVersion(versions?: readonly ApiVersion[]): ApiVersion;
|
|
39
|
+
export declare function findVersion(id: string, versions?: readonly ApiVersion[]): ApiVersion | undefined;
|
|
40
|
+
/** A request body written for version `from`, translated up to the latest version. */
|
|
41
|
+
export declare function translateRequest(from: string, operationId: string, body: unknown, versions?: readonly ApiVersion[]): unknown;
|
|
42
|
+
/** A response body from the latest version, translated down to version `to`. */
|
|
43
|
+
export declare function translateResponse(to: string, operationId: string, status: number, body: unknown, versions?: readonly ApiVersion[]): unknown;
|
|
44
|
+
/** A webhook payload's `data` from the latest version, translated down to the receiver's pin. */
|
|
45
|
+
export declare function translateEvent(to: string, type: string, data: unknown, versions?: readonly ApiVersion[]): unknown;
|
|
46
|
+
//# sourceMappingURL=versions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"versions.d.ts","sourceRoot":"","sources":["../src/versions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,UAAU,CAAC;AAEnD,MAAM,WAAW,aAAa;IAC5B,6CAA6C;IAC7C,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,KAAK,OAAO,CAAC;IAC9D,mFAAmF;IACnF,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,KAAK,OAAO,CAAC;IAChF,8FAA8F;IAC9F,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,KAAK,OAAO,CAAC;CAC/D;AAED,MAAM,WAAW,UAAU;IACzB,oBAAoB;IACpB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IAC/B,oEAAoE;IACpE,QAAQ,CAAC,OAAO,EAAE,SAAS,aAAa,EAAE,CAAC;CAC5C;AAED,eAAO,MAAM,cAAc,sBAAsB,CAAC;AAClD,eAAO,MAAM,eAAe,2BAA2B,CAAC;AAExD,sEAAsE;AACtE,eAAO,MAAM,QAAQ,EAAE,SAAS,UAAU,EAEzC,CAAC;AAEF,wBAAgB,aAAa,CAAC,QAAQ,GAAE,SAAS,UAAU,EAAa,GAAG,UAAU,CAIpF;AAED,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,GAAE,SAAS,UAAU,EAAa,GAAG,UAAU,GAAG,SAAS,CAE1G;AASD,sFAAsF;AACtF,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,OAAO,EACb,QAAQ,GAAE,SAAS,UAAU,EAAa,GACzC,OAAO,CAET;AAED,gFAAgF;AAChF,wBAAgB,iBAAiB,CAC/B,EAAE,EAAE,MAAM,EACV,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,OAAO,EACb,QAAQ,GAAE,SAAS,UAAU,EAAa,GACzC,OAAO,CAIT;AAED,iGAAiG;AACjG,wBAAgB,cAAc,CAC5B,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,OAAO,EACb,QAAQ,GAAE,SAAS,UAAU,EAAa,GACzC,OAAO,CAIT"}
|