@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
package/dist/op.js
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { Problem } from "./common.js";
|
|
2
|
+
import { VERSION_PATTERN } from "./versions.js";
|
|
3
|
+
import { z } from "./zod.js";
|
|
4
|
+
export const TAGS = {
|
|
5
|
+
meta: "The contract describing itself: its dated versions, its OpenAPI documents, and the keys Indorania signs webhooks with.",
|
|
6
|
+
trust: "The trust list: which issuers a wallet shows as listed (holder contract §3). A policy, never the format (ECOSYSTEM d47(e)).",
|
|
7
|
+
backup: "A person's optional account holds one encrypted blob and nothing else (ADR-0001, d47(f)).",
|
|
8
|
+
organisations: "Businesses, institutes and houses. A house is an organisation whose door opens on place, craft or goal — never on birth (d47(c)).",
|
|
9
|
+
seats: "Staff logins and their roles in one organisation. For a house, its stewards — never its members, whom the platform never lists.",
|
|
10
|
+
"guest-links": "A counterparty with no account countersigns through a link: one click, no install, no password (d26, d47(f)).",
|
|
11
|
+
capabilities: "What an establishment does — visits, money in and out, work and jobs — and the portal sections integrations register for each (architecture §7.2, without brands).",
|
|
12
|
+
entitlements: "Which capabilities an organisation runs, at which capacity. Granted by payment, sponsorship, trial or the simulation, and never read from billing (d50(f)).",
|
|
13
|
+
asks: "The public ask library (d42 §5): requests for evidence, answered with a yes and never with the data.",
|
|
14
|
+
presentations: "One presentation request per encounter, answered by a wallet over OpenID for Verifiable Presentations. A decline sends nothing and leaves no trace (d49(a)).",
|
|
15
|
+
standing: "Standing is derived on request from presented predicates, signed and expiring; nothing that links is kept (d42 §2, d47(d)).",
|
|
16
|
+
sessions: "One encounter, both signatures on every line. Indorania relays and anchors, and never signs as a party (d47(d)).",
|
|
17
|
+
"thank-yous": "A counterparty's promise to a person who answered — never Indorania's, never a balance (d49(b)).",
|
|
18
|
+
issuance: "OpenID for Verifiable Credential Issuance 1.0 endpoints for credentials the platform issues on an organisation's behalf, such as thank-yous. Standard, so exempt from dated versions.",
|
|
19
|
+
integration: "How a member's or an outside issuer's system joins: its issuer, its predicate-answer and session-event webhooks, and its portal sections — the same contract for everyone (d47(a)).",
|
|
20
|
+
};
|
|
21
|
+
export const VersionHeader = z
|
|
22
|
+
.string()
|
|
23
|
+
.regex(new RegExp(VERSION_PATTERN))
|
|
24
|
+
.meta({
|
|
25
|
+
id: "IndoraniaVersion",
|
|
26
|
+
description: "The dated API version this request speaks (YYYY-MM-DD). Without it, the caller's pinned version applies; with no pin, the request is refused.",
|
|
27
|
+
})
|
|
28
|
+
.optional();
|
|
29
|
+
/** IETF draft-ietf-httpapi-idempotency-key-header-07: a quoted Structured-Field string. The bare form is also accepted. */
|
|
30
|
+
export const IdempotencyKeyHeader = z
|
|
31
|
+
.string()
|
|
32
|
+
.regex(/^(?:"[A-Za-z0-9._~:-]{8,255}"|[A-Za-z0-9._~:-]{8,255})$/)
|
|
33
|
+
.meta({
|
|
34
|
+
id: "IdempotencyKey",
|
|
35
|
+
description: "A fresh random value (a UUID) per change. Kept 24 hours: a retry with the same key and body gets the first answer; the same key with another body is refused (422); a key still running is refused (409).",
|
|
36
|
+
});
|
|
37
|
+
export const WebhookHeaders = {
|
|
38
|
+
"webhook-id": z.string().min(1).max(255).meta({ id: "WebhookId", description: "Standard Webhooks 1.0.0. Unique per message; it is also the idempotency key." }),
|
|
39
|
+
"webhook-timestamp": z.string().regex(/^\d{1,12}$/).meta({ id: "WebhookTimestamp", description: "Unix seconds. Refused if more than 300 seconds from the receiver's clock." }),
|
|
40
|
+
"webhook-signature": z
|
|
41
|
+
.string()
|
|
42
|
+
.regex(/^\S+,\S+( \S+,\S+)*$/)
|
|
43
|
+
.meta({ id: "WebhookSignature", description: "Space-separated `v1a,<base64 Ed25519 signature>` over `webhook-id.webhook-timestamp.body`." }),
|
|
44
|
+
};
|
|
45
|
+
const PROBLEM_RESPONSE = {
|
|
46
|
+
description: "A problem (RFC 9457). Every error of this API has this shape.",
|
|
47
|
+
content: { "application/problem+json": { schema: Problem } },
|
|
48
|
+
};
|
|
49
|
+
export function operation(spec) {
|
|
50
|
+
const versioning = spec.versioning ?? "dated";
|
|
51
|
+
const mutating = spec.method !== "get";
|
|
52
|
+
if (mutating && !spec.idempotency)
|
|
53
|
+
throw new Error(`${spec.operationId}: a mutation must declare its idempotency`);
|
|
54
|
+
if (!mutating && spec.idempotency)
|
|
55
|
+
throw new Error(`${spec.operationId}: a read declares no idempotency`);
|
|
56
|
+
if (spec.collection && spec.method !== "get")
|
|
57
|
+
throw new Error(`${spec.operationId}: only a read can be a collection`);
|
|
58
|
+
const headers = {};
|
|
59
|
+
if (versioning === "dated")
|
|
60
|
+
headers["indorania-version"] = VersionHeader;
|
|
61
|
+
if (spec.idempotency === "key")
|
|
62
|
+
headers["idempotency-key"] = IdempotencyKeyHeader;
|
|
63
|
+
if (spec.idempotency === "webhook-id")
|
|
64
|
+
Object.assign(headers, WebhookHeaders);
|
|
65
|
+
Object.assign(headers, spec.headers ?? {});
|
|
66
|
+
const request = {};
|
|
67
|
+
if (spec.params)
|
|
68
|
+
request.params = spec.params;
|
|
69
|
+
if (spec.query)
|
|
70
|
+
request.query = spec.query;
|
|
71
|
+
if (Object.keys(headers).length > 0)
|
|
72
|
+
request.headers = z.object(headers);
|
|
73
|
+
if (spec.body) {
|
|
74
|
+
request.body = {
|
|
75
|
+
required: true,
|
|
76
|
+
...(spec.body.description ? { description: spec.body.description } : {}),
|
|
77
|
+
content: { [spec.body.type ?? "application/json"]: { schema: spec.body.schema } },
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
const responses = {};
|
|
81
|
+
for (const [status, r] of Object.entries(spec.responses)) {
|
|
82
|
+
responses[status] = r.schema
|
|
83
|
+
? { description: r.description, content: { [r.type ?? "application/json"]: { schema: r.schema } } }
|
|
84
|
+
: { description: r.description };
|
|
85
|
+
}
|
|
86
|
+
responses.default = PROBLEM_RESPONSE;
|
|
87
|
+
const meta = {
|
|
88
|
+
operationId: spec.operationId,
|
|
89
|
+
method: spec.method,
|
|
90
|
+
path: spec.path,
|
|
91
|
+
pending: spec.pending,
|
|
92
|
+
versioning,
|
|
93
|
+
idempotency: spec.idempotency ?? null,
|
|
94
|
+
auth: spec.auth,
|
|
95
|
+
};
|
|
96
|
+
const route = {
|
|
97
|
+
method: spec.method,
|
|
98
|
+
path: spec.path,
|
|
99
|
+
operationId: spec.operationId,
|
|
100
|
+
tags: [spec.tag],
|
|
101
|
+
summary: spec.summary,
|
|
102
|
+
...(spec.description ? { description: spec.description } : {}),
|
|
103
|
+
security: spec.auth.map((scheme) => ({ [scheme]: [] })),
|
|
104
|
+
request,
|
|
105
|
+
responses,
|
|
106
|
+
...(spec.pending ? { "x-indorania-pending": spec.pending } : {}),
|
|
107
|
+
"x-indorania-versioning": versioning,
|
|
108
|
+
...(spec.idempotency ? { "x-indorania-idempotency": spec.idempotency } : {}),
|
|
109
|
+
...(spec.collection ? { "x-indorania-collection": spec.collection } : {}),
|
|
110
|
+
};
|
|
111
|
+
return { route, meta };
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=op.js.map
|
package/dist/op.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"op.js","sourceRoot":"","sources":["../src/op.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { z } from "../zod.ts";
|
|
2
|
+
/** A predicate kind, as members publish them. Never the improvement item (d43), never origin (d36). */
|
|
3
|
+
export declare const PredicateKind: z.ZodString;
|
|
4
|
+
export declare const AskKey: z.ZodString;
|
|
5
|
+
export declare const AskNeed: z.ZodObject<{
|
|
6
|
+
id: z.ZodString;
|
|
7
|
+
predicate: z.ZodString;
|
|
8
|
+
withinDays: z.ZodNumber;
|
|
9
|
+
issuers: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
10
|
+
}, z.core.$strict>;
|
|
11
|
+
export declare const Ask: z.ZodObject<{
|
|
12
|
+
format: z.ZodLiteral<"kashscript-ask/1">;
|
|
13
|
+
key: z.ZodString;
|
|
14
|
+
version: z.ZodNumber;
|
|
15
|
+
title: z.ZodString;
|
|
16
|
+
who: z.ZodObject<{
|
|
17
|
+
name: z.ZodString;
|
|
18
|
+
id: z.ZodString;
|
|
19
|
+
}, z.core.$strict>;
|
|
20
|
+
needs: z.ZodArray<z.ZodObject<{
|
|
21
|
+
id: z.ZodString;
|
|
22
|
+
predicate: z.ZodString;
|
|
23
|
+
withinDays: z.ZodNumber;
|
|
24
|
+
issuers: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
25
|
+
}, z.core.$strict>>;
|
|
26
|
+
why: z.ZodString;
|
|
27
|
+
answer: z.ZodObject<{
|
|
28
|
+
form: z.ZodLiteral<"yes">;
|
|
29
|
+
restsOn: z.ZodLiteral<"issuers">;
|
|
30
|
+
}, z.core.$strict>;
|
|
31
|
+
goodFor: z.ZodString;
|
|
32
|
+
declining: z.ZodLiteral<"costs-only-goodFor">;
|
|
33
|
+
linking: z.ZodLiteral<"separate">;
|
|
34
|
+
published: z.ZodObject<{
|
|
35
|
+
library: z.ZodString;
|
|
36
|
+
atUnix: z.ZodNumber;
|
|
37
|
+
}, z.core.$strict>;
|
|
38
|
+
expiresAtUnix: z.ZodNumber;
|
|
39
|
+
state: z.ZodEnum<{
|
|
40
|
+
published: "published";
|
|
41
|
+
withdrawn: "withdrawn";
|
|
42
|
+
expired: "expired";
|
|
43
|
+
}>;
|
|
44
|
+
}, z.core.$strict>;
|
|
45
|
+
/**
|
|
46
|
+
* What a verifier writes. The library fills the rest — the format, the verifier, the fixed
|
|
47
|
+
* answer, declining and linking, where and when it is published — and attest's validator checks
|
|
48
|
+
* the whole ask here, at the edge, with now as its publication time.
|
|
49
|
+
*/
|
|
50
|
+
export declare const AskDraft: z.ZodObject<{
|
|
51
|
+
key: z.ZodString;
|
|
52
|
+
version: z.ZodNumber;
|
|
53
|
+
title: z.ZodString;
|
|
54
|
+
needs: z.ZodArray<z.ZodObject<{
|
|
55
|
+
id: z.ZodString;
|
|
56
|
+
predicate: z.ZodString;
|
|
57
|
+
withinDays: z.ZodNumber;
|
|
58
|
+
issuers: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
59
|
+
}, z.core.$strict>>;
|
|
60
|
+
why: z.ZodString;
|
|
61
|
+
goodFor: z.ZodString;
|
|
62
|
+
expiresAtUnix: z.ZodNumber;
|
|
63
|
+
}, z.core.$strict>;
|
|
64
|
+
export declare const AskAnswer: z.ZodObject<{
|
|
65
|
+
capability: z.ZodEnum<{
|
|
66
|
+
visits: "visits";
|
|
67
|
+
money: "money";
|
|
68
|
+
work: "work";
|
|
69
|
+
}>;
|
|
70
|
+
needs: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
71
|
+
}, z.core.$strict>;
|
|
72
|
+
export declare const AskAnswerRouted: z.ZodObject<{
|
|
73
|
+
answer: z.ZodString;
|
|
74
|
+
expiresAtUnix: z.ZodNumber;
|
|
75
|
+
}, z.core.$strict>;
|
|
76
|
+
export declare const askOperations: import("../op.ts").Operation[];
|
|
77
|
+
//# sourceMappingURL=asks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"asks.d.ts","sourceRoot":"","sources":["../../src/routes/asks.ts"],"names":[],"mappings":"AAoBA,OAAO,EAAE,CAAC,EAAE,MAAM,WAAW,CAAC;AAM9B,uGAAuG;AACvG,eAAO,MAAM,aAAa,aAStB,CAAC;AAEL,eAAO,MAAM,MAAM,aAAoJ,CAAC;AAGxK,eAAO,MAAM,OAAO;;;;;kBAQM,CAAC;AAM3B,eAAO,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAsBZ,CAAC;AAWL;;;;GAIG;AACH,eAAO,MAAM,QAAQ;;;;;;;;;;;;;kBA2BmI,CAAC;AAEzJ,eAAO,MAAM,SAAS;;;;;;;kBAMiI,CAAC;AAExJ,eAAO,MAAM,eAAe;;;kBAMxB,CAAC;AAKL,eAAO,MAAM,aAAa,gCA+DzB,CAAC"}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The public ask library (d42 §5, d47(d)). The ask is PL-3's format, `kashscript-ask/1`: this
|
|
3
|
+
* schema is built from the constants @kashscript/attest publishes, and a publish is checked by
|
|
4
|
+
* attest's own `validateAsk` — so the eight rules and the forbidden needs are one source, never a
|
|
5
|
+
* copy (test/asks.test.ts holds the two in step).
|
|
6
|
+
*/
|
|
7
|
+
import { ASK_FORMAT, ASK_KEY_PATTERN, ASK_MAX_LIFETIME_SEC, ASK_STATES, DECLINING_CONST, FORBIDDEN_NEED_PATTERN, IMPROVEMENT_PATTERN, LINKING_CONST, PREDICATE_KIND_PATTERN, validateAsk, } from "@kashscript/attest/exchange";
|
|
8
|
+
import { AnswerId, UnixTime, pageOf, PageQuery } from "../common.js";
|
|
9
|
+
import { operation } from "../op.js";
|
|
10
|
+
import { z } from "../zod.js";
|
|
11
|
+
import { Capability } from "./capabilities.js";
|
|
12
|
+
const improvement = new RegExp(IMPROVEMENT_PATTERN, "i");
|
|
13
|
+
const forbidden = new RegExp(FORBIDDEN_NEED_PATTERN, "i");
|
|
14
|
+
/** A predicate kind, as members publish them. Never the improvement item (d43), never origin (d36). */
|
|
15
|
+
export const PredicateKind = z
|
|
16
|
+
.string()
|
|
17
|
+
.regex(new RegExp(PREDICATE_KIND_PATTERN))
|
|
18
|
+
.refine((k) => !improvement.test(k), { message: "an ask may never require the improvement item (d43)", params: { rule: "R8-no-improvement-item" } })
|
|
19
|
+
.refine((k) => !forbidden.test(k), { message: "no ask refers to origin, ethnicity, sect, caste or ancestry (d36)", params: { rule: "FORBIDDEN-NEED" } })
|
|
20
|
+
.meta({
|
|
21
|
+
id: "PredicateKind",
|
|
22
|
+
description: "A predicate kind — never a record, a field or an attachment (rule 1). Never the improvement item (rule 8, d43); never origin, ethnicity, sect, caste or ancestry (d36).",
|
|
23
|
+
not: { anyOf: [{ pattern: IMPROVEMENT_PATTERN }, { pattern: FORBIDDEN_NEED_PATTERN }] },
|
|
24
|
+
});
|
|
25
|
+
export const AskKey = z.string().regex(new RegExp(ASK_KEY_PATTERN)).meta({ id: "AskKey", description: "Rule 7: a stable key a holder's excessive-ask note can name." });
|
|
26
|
+
const AskVersion = z.number().int().min(1);
|
|
27
|
+
export const AskNeed = z
|
|
28
|
+
.object({
|
|
29
|
+
id: z.string().min(1),
|
|
30
|
+
predicate: PredicateKind,
|
|
31
|
+
withinDays: z.number().int().min(1),
|
|
32
|
+
issuers: z.array(z.string()).optional().meta({ description: "Only these issuers' yes counts." }),
|
|
33
|
+
})
|
|
34
|
+
.strict()
|
|
35
|
+
.meta({ id: "AskNeed" });
|
|
36
|
+
const Needs = z.array(AskNeed).min(1).meta({ description: "Rule 1: predicate kinds only. Rule 6: no kind asked twice." });
|
|
37
|
+
const Why = z.string().min(12).meta({ description: "Rule 2: why, in plain words, saying more than the title." });
|
|
38
|
+
const GoodFor = z.string().min(1).meta({ description: "Rule 3: what a yes gets the holder. Declining costs this and nothing more." });
|
|
39
|
+
export const Ask = z
|
|
40
|
+
.object({
|
|
41
|
+
format: z.literal(ASK_FORMAT),
|
|
42
|
+
key: AskKey,
|
|
43
|
+
version: AskVersion,
|
|
44
|
+
title: z.string().min(1),
|
|
45
|
+
who: z.object({ name: z.string(), id: z.string().min(1).meta({ description: "The verifier: the OpenID4VP client_id and the KB-JWT audience." }) }).strict(),
|
|
46
|
+
needs: Needs,
|
|
47
|
+
why: Why,
|
|
48
|
+
answer: z.object({ form: z.literal("yes"), restsOn: z.literal("issuers") }).strict(),
|
|
49
|
+
goodFor: GoodFor,
|
|
50
|
+
declining: z.literal(DECLINING_CONST),
|
|
51
|
+
linking: z.literal(LINKING_CONST),
|
|
52
|
+
published: z.object({ library: z.string().regex(/^https:\/\//), atUnix: z.number().int() }).strict(),
|
|
53
|
+
expiresAtUnix: z.number().int().meta({ description: "Rule 4: at most 366 days after publication." }),
|
|
54
|
+
state: z.enum(ASK_STATES),
|
|
55
|
+
})
|
|
56
|
+
.strict()
|
|
57
|
+
.meta({
|
|
58
|
+
id: "Ask",
|
|
59
|
+
description: "kashscript-ask/1 (specs/presentation.md §1): a published request for evidence, answered with a yes and never with the data.",
|
|
60
|
+
"x-kash-maxLifetimeSec": ASK_MAX_LIFETIME_SEC,
|
|
61
|
+
});
|
|
62
|
+
/** attest reports `$.needs[0].predicate`; the error envelope takes a path array. */
|
|
63
|
+
function toPath(path) {
|
|
64
|
+
return path
|
|
65
|
+
.replace(/^\$\.?/, "")
|
|
66
|
+
.split(/[.[\]]/)
|
|
67
|
+
.filter(Boolean)
|
|
68
|
+
.map((p) => (/^\d+$/.test(p) ? Number(p) : p));
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* What a verifier writes. The library fills the rest — the format, the verifier, the fixed
|
|
72
|
+
* answer, declining and linking, where and when it is published — and attest's validator checks
|
|
73
|
+
* the whole ask here, at the edge, with now as its publication time.
|
|
74
|
+
*/
|
|
75
|
+
export const AskDraft = z
|
|
76
|
+
.object({
|
|
77
|
+
key: AskKey,
|
|
78
|
+
version: AskVersion,
|
|
79
|
+
title: z.string().min(1),
|
|
80
|
+
needs: Needs,
|
|
81
|
+
why: Why,
|
|
82
|
+
goodFor: GoodFor,
|
|
83
|
+
expiresAtUnix: z.number().int(),
|
|
84
|
+
})
|
|
85
|
+
.strict()
|
|
86
|
+
.superRefine((draft, ctx) => {
|
|
87
|
+
const now = Math.floor(Date.now() / 1000);
|
|
88
|
+
const { violations } = validateAsk({
|
|
89
|
+
format: ASK_FORMAT,
|
|
90
|
+
...draft,
|
|
91
|
+
who: { name: "draft", id: "draft" },
|
|
92
|
+
answer: { form: "yes", restsOn: "issuers" },
|
|
93
|
+
declining: DECLINING_CONST,
|
|
94
|
+
linking: LINKING_CONST,
|
|
95
|
+
published: { library: "https://library.invalid", atUnix: now },
|
|
96
|
+
state: "published",
|
|
97
|
+
});
|
|
98
|
+
for (const v of violations) {
|
|
99
|
+
ctx.addIssue({ code: "custom", message: v.message, path: toPath(v.path), params: { rule: v.rule } });
|
|
100
|
+
}
|
|
101
|
+
})
|
|
102
|
+
.meta({ id: "AskDraft", description: "An ask as a verifier writes it. The eight rules and the forbidden needs are checked by attest's validateAsk." });
|
|
103
|
+
export const AskAnswer = z
|
|
104
|
+
.object({
|
|
105
|
+
capability: Capability,
|
|
106
|
+
needs: z.array(z.string().min(1)).min(1).optional().meta({ description: "The needs you answer; all of them when absent." }),
|
|
107
|
+
})
|
|
108
|
+
.strict()
|
|
109
|
+
.meta({ id: "AskAnswer", description: "`capability` names which of your books answers: the platform routes the ask to the integration running it." });
|
|
110
|
+
export const AskAnswerRouted = z
|
|
111
|
+
.object({ answer: AnswerId, expiresAtUnix: UnixTime })
|
|
112
|
+
.strict()
|
|
113
|
+
.meta({
|
|
114
|
+
id: "AskAnswerRouted",
|
|
115
|
+
description: "Routed. Only a yes ever reaches the verifier; \"does not hold\" comes back to you alone, and nothing records it.",
|
|
116
|
+
});
|
|
117
|
+
const KeyParams = z.object({ key: AskKey }).strict();
|
|
118
|
+
const KeyVersionParams = z.object({ key: AskKey, version: z.coerce.number().int().min(1) }).strict();
|
|
119
|
+
export const askOperations = [
|
|
120
|
+
operation({
|
|
121
|
+
operationId: "publishAsk",
|
|
122
|
+
method: "post",
|
|
123
|
+
path: "/v1/asks",
|
|
124
|
+
tag: "asks",
|
|
125
|
+
summary: "Publish an ask to the public library",
|
|
126
|
+
auth: ["seat"],
|
|
127
|
+
pending: "PL-8",
|
|
128
|
+
idempotency: "key",
|
|
129
|
+
body: { schema: AskDraft },
|
|
130
|
+
responses: { 201: { description: "Published.", schema: Ask } },
|
|
131
|
+
}),
|
|
132
|
+
operation({
|
|
133
|
+
operationId: "listAsks",
|
|
134
|
+
method: "get",
|
|
135
|
+
path: "/v1/asks",
|
|
136
|
+
tag: "asks",
|
|
137
|
+
summary: "The public ask library",
|
|
138
|
+
description: "Public, so what establishments ask of people is as auditable as the records themselves (d42 §5, rule 5).",
|
|
139
|
+
auth: [],
|
|
140
|
+
pending: "PL-8",
|
|
141
|
+
collection: "The ask library is public by design (d42 §5 rule 5). Asks are demands made of people, never people or records.",
|
|
142
|
+
query: PageQuery.extend({ state: z.enum(ASK_STATES).optional() }),
|
|
143
|
+
responses: { 200: { description: "One page of asks.", schema: pageOf(Ask, "AskPage") } },
|
|
144
|
+
}),
|
|
145
|
+
operation({
|
|
146
|
+
operationId: "getAsk",
|
|
147
|
+
method: "get",
|
|
148
|
+
path: "/v1/asks/{key}",
|
|
149
|
+
tag: "asks",
|
|
150
|
+
summary: "An ask's latest version",
|
|
151
|
+
auth: [],
|
|
152
|
+
pending: "PL-8",
|
|
153
|
+
params: KeyParams,
|
|
154
|
+
responses: { 200: { description: "The ask.", schema: Ask } },
|
|
155
|
+
}),
|
|
156
|
+
operation({
|
|
157
|
+
operationId: "getAskVersion",
|
|
158
|
+
method: "get",
|
|
159
|
+
path: "/v1/asks/{key}/versions/{version}",
|
|
160
|
+
tag: "asks",
|
|
161
|
+
summary: "One version of an ask",
|
|
162
|
+
auth: [],
|
|
163
|
+
pending: "PL-8",
|
|
164
|
+
params: KeyVersionParams,
|
|
165
|
+
responses: { 200: { description: "The ask.", schema: Ask } },
|
|
166
|
+
}),
|
|
167
|
+
operation({
|
|
168
|
+
operationId: "answerAsk",
|
|
169
|
+
method: "post",
|
|
170
|
+
path: "/v1/asks/{key}/versions/{version}/answers",
|
|
171
|
+
tag: "asks",
|
|
172
|
+
summary: "Answer an ask from your own book",
|
|
173
|
+
description: "For an organisation. The platform asks the integration that runs your book for that capability, through its predicate-answer webhook. A person answers in their wallet instead, through a presentation request.",
|
|
174
|
+
auth: ["seat"],
|
|
175
|
+
pending: "PL-8",
|
|
176
|
+
idempotency: "key",
|
|
177
|
+
params: KeyVersionParams,
|
|
178
|
+
body: { schema: AskAnswer },
|
|
179
|
+
responses: { 202: { description: "Routed.", schema: AskAnswerRouted } },
|
|
180
|
+
}),
|
|
181
|
+
];
|
|
182
|
+
//# sourceMappingURL=asks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"asks.js","sourceRoot":"","sources":["../../src/routes/asks.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { z } from "../zod.ts";
|
|
2
|
+
export declare const BACKUP_MAX_BYTES: number;
|
|
3
|
+
export declare const Backup: z.ZodObject<{
|
|
4
|
+
ciphertext: z.ZodString;
|
|
5
|
+
version: z.ZodNumber;
|
|
6
|
+
updatedAtUnix: z.ZodNumber;
|
|
7
|
+
}, z.core.$strict>;
|
|
8
|
+
export declare const BackupWrite: z.ZodObject<{
|
|
9
|
+
ciphertext: z.ZodString;
|
|
10
|
+
}, z.core.$strict>;
|
|
11
|
+
export declare const backupOperations: import("../op.ts").Operation[];
|
|
12
|
+
//# sourceMappingURL=backup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backup.d.ts","sourceRoot":"","sources":["../../src/routes/backup.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,WAAW,CAAC;AAE9B,eAAO,MAAM,gBAAgB,QAAmB,CAAC;AAWjD,eAAO,MAAM,MAAM;;;;kBAWf,CAAC;AAEL,eAAO,MAAM,WAAW;;kBAA4E,CAAC;AAErG,eAAO,MAAM,gBAAgB,gCAqC5B,CAAC"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/** A person's optional account: one encrypted blob and nothing else (ADR-0001, d47(f)). */
|
|
2
|
+
import { UnixTime } from "../common.js";
|
|
3
|
+
import { operation } from "../op.js";
|
|
4
|
+
import { z } from "../zod.js";
|
|
5
|
+
export const BACKUP_MAX_BYTES = 16 * 1024 * 1024;
|
|
6
|
+
const Ciphertext = z
|
|
7
|
+
.string()
|
|
8
|
+
.regex(/^[A-Za-z0-9_-]+$/)
|
|
9
|
+
.max(Math.ceil(BACKUP_MAX_BYTES / 3) * 4)
|
|
10
|
+
.meta({
|
|
11
|
+
description: "base64url of ciphertext the person's own device made, at most 16 MiB. The platform never holds the key that opens it, and it can read nothing inside.",
|
|
12
|
+
});
|
|
13
|
+
export const Backup = z
|
|
14
|
+
.object({
|
|
15
|
+
ciphertext: Ciphertext,
|
|
16
|
+
version: z.number().int().min(1).meta({ description: "Increases by one on every write. Send it back as If-Match." }),
|
|
17
|
+
updatedAtUnix: UnixTime,
|
|
18
|
+
})
|
|
19
|
+
.strict()
|
|
20
|
+
.meta({
|
|
21
|
+
id: "Backup",
|
|
22
|
+
description: "Everything a person's account holds. It binds no DID, relationship id, key, record or push token, and is never linked to a seat (ADR-0001).",
|
|
23
|
+
});
|
|
24
|
+
export const BackupWrite = z.object({ ciphertext: Ciphertext }).strict().meta({ id: "BackupWrite" });
|
|
25
|
+
export const backupOperations = [
|
|
26
|
+
operation({
|
|
27
|
+
operationId: "getBackup",
|
|
28
|
+
method: "get",
|
|
29
|
+
path: "/v1/backup",
|
|
30
|
+
tag: "backup",
|
|
31
|
+
summary: "Read the encrypted backup",
|
|
32
|
+
auth: ["personAccount"],
|
|
33
|
+
pending: null,
|
|
34
|
+
responses: { 200: { description: "The blob and its version.", schema: Backup } },
|
|
35
|
+
}),
|
|
36
|
+
operation({
|
|
37
|
+
operationId: "putBackup",
|
|
38
|
+
method: "put",
|
|
39
|
+
path: "/v1/backup",
|
|
40
|
+
tag: "backup",
|
|
41
|
+
summary: "Write the encrypted backup",
|
|
42
|
+
description: "The first write needs no If-Match. Every later write sends the version it read, so two devices never overwrite each other unseen (412 version_conflict).",
|
|
43
|
+
auth: ["personAccount"],
|
|
44
|
+
pending: null,
|
|
45
|
+
idempotency: "key",
|
|
46
|
+
headers: { "if-match": z.string().regex(/^"\d+"$/).optional().meta({ description: 'The version last read, quoted: "3".' }) },
|
|
47
|
+
body: { schema: BackupWrite },
|
|
48
|
+
responses: { 200: { description: "Stored.", schema: Backup } },
|
|
49
|
+
}),
|
|
50
|
+
operation({
|
|
51
|
+
operationId: "deleteBackup",
|
|
52
|
+
method: "delete",
|
|
53
|
+
path: "/v1/backup",
|
|
54
|
+
tag: "backup",
|
|
55
|
+
summary: "Delete the encrypted backup",
|
|
56
|
+
description: "Deleting it breaks nothing: holding, presenting and checking never depend on the account.",
|
|
57
|
+
auth: ["personAccount"],
|
|
58
|
+
pending: null,
|
|
59
|
+
idempotency: "key",
|
|
60
|
+
responses: { 204: { description: "Gone." } },
|
|
61
|
+
}),
|
|
62
|
+
];
|
|
63
|
+
//# sourceMappingURL=backup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backup.js","sourceRoot":"","sources":["../../src/routes/backup.ts"],"names":[],"mappings":"AAAA,2FAA2F;AAC3F,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACrC,OAAO,EAAE,CAAC,EAAE,MAAM,WAAW,CAAC;AAE9B,MAAM,CAAC,MAAM,gBAAgB,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC;AAEjD,MAAM,UAAU,GAAG,CAAC;KACjB,MAAM,EAAE;KACR,KAAK,CAAC,kBAAkB,CAAC;KACzB,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;KACxC,IAAI,CAAC;IACJ,WAAW,EACT,uJAAuJ;CAC1J,CAAC,CAAC;AAEL,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC;KACpB,MAAM,CAAC;IACN,UAAU,EAAE,UAAU;IACtB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,WAAW,EAAE,4DAA4D,EAAE,CAAC;IACpH,aAAa,EAAE,QAAQ;CACxB,CAAC;KACD,MAAM,EAAE;KACR,IAAI,CAAC;IACJ,EAAE,EAAE,QAAQ;IACZ,WAAW,EACT,6IAA6I;CAChJ,CAAC,CAAC;AAEL,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,aAAa,EAAE,CAAC,CAAC;AAErG,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,SAAS,CAAC;QACR,WAAW,EAAE,WAAW;QACxB,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,YAAY;QAClB,GAAG,EAAE,QAAQ;QACb,OAAO,EAAE,2BAA2B;QACpC,IAAI,EAAE,CAAC,eAAe,CAAC;QACvB,OAAO,EAAE,IAAI;QACb,SAAS,EAAE,EAAE,GAAG,EAAE,EAAE,WAAW,EAAE,2BAA2B,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;KACjF,CAAC;IACF,SAAS,CAAC;QACR,WAAW,EAAE,WAAW;QACxB,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,YAAY;QAClB,GAAG,EAAE,QAAQ;QACb,OAAO,EAAE,4BAA4B;QACrC,WAAW,EAAE,0JAA0J;QACvK,IAAI,EAAE,CAAC,eAAe,CAAC;QACvB,OAAO,EAAE,IAAI;QACb,WAAW,EAAE,KAAK;QAClB,OAAO,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,EAAE,WAAW,EAAE,qCAAqC,EAAE,CAAC,EAAE;QAC5H,IAAI,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE;QAC7B,SAAS,EAAE,EAAE,GAAG,EAAE,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;KAC/D,CAAC;IACF,SAAS,CAAC;QACR,WAAW,EAAE,cAAc;QAC3B,MAAM,EAAE,QAAQ;QAChB,IAAI,EAAE,YAAY;QAClB,GAAG,EAAE,QAAQ;QACb,OAAO,EAAE,6BAA6B;QACtC,WAAW,EAAE,2FAA2F;QACxG,IAAI,EAAE,CAAC,eAAe,CAAC;QACvB,OAAO,EAAE,IAAI;QACb,WAAW,EAAE,KAAK;QAClB,SAAS,EAAE,EAAE,GAAG,EAAE,EAAE,WAAW,EAAE,OAAO,EAAE,EAAE;KAC7C,CAAC;CACH,CAAC"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { z } from "../zod.ts";
|
|
2
|
+
export declare const CAPABILITIES: readonly ["visits", "money", "work"];
|
|
3
|
+
export declare const Capability: z.ZodEnum<{
|
|
4
|
+
visits: "visits";
|
|
5
|
+
money: "money";
|
|
6
|
+
work: "work";
|
|
7
|
+
}>;
|
|
8
|
+
export declare const SectionId: z.ZodString;
|
|
9
|
+
export declare const CapabilityManifest: z.ZodObject<{
|
|
10
|
+
format: z.ZodLiteral<"indorania-capability-manifest/1">;
|
|
11
|
+
id: z.ZodString;
|
|
12
|
+
capability: z.ZodEnum<{
|
|
13
|
+
visits: "visits";
|
|
14
|
+
money: "money";
|
|
15
|
+
work: "work";
|
|
16
|
+
}>;
|
|
17
|
+
version: z.ZodNumber;
|
|
18
|
+
permissions: z.ZodArray<z.ZodString>;
|
|
19
|
+
settings: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
20
|
+
surfaces: z.ZodObject<{
|
|
21
|
+
nav: z.ZodObject<{
|
|
22
|
+
group: z.ZodString;
|
|
23
|
+
label: z.ZodString;
|
|
24
|
+
icon: z.ZodString;
|
|
25
|
+
}, z.core.$strict>;
|
|
26
|
+
routes: z.ZodArray<z.ZodString>;
|
|
27
|
+
widgets: z.ZodArray<z.ZodString>;
|
|
28
|
+
}, z.core.$strict>;
|
|
29
|
+
onboarding: z.ZodArray<z.ZodString>;
|
|
30
|
+
events: z.ZodArray<z.ZodString>;
|
|
31
|
+
apiScopes: z.ZodArray<z.ZodString>;
|
|
32
|
+
}, z.core.$strict>;
|
|
33
|
+
export declare const OrganisationCapabilities: z.ZodObject<{
|
|
34
|
+
capabilities: z.ZodArray<z.ZodObject<{
|
|
35
|
+
capability: z.ZodEnum<{
|
|
36
|
+
visits: "visits";
|
|
37
|
+
money: "money";
|
|
38
|
+
work: "work";
|
|
39
|
+
}>;
|
|
40
|
+
sections: z.ZodArray<z.ZodObject<{
|
|
41
|
+
format: z.ZodLiteral<"indorania-capability-manifest/1">;
|
|
42
|
+
id: z.ZodString;
|
|
43
|
+
capability: z.ZodEnum<{
|
|
44
|
+
visits: "visits";
|
|
45
|
+
money: "money";
|
|
46
|
+
work: "work";
|
|
47
|
+
}>;
|
|
48
|
+
version: z.ZodNumber;
|
|
49
|
+
permissions: z.ZodArray<z.ZodString>;
|
|
50
|
+
settings: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
51
|
+
surfaces: z.ZodObject<{
|
|
52
|
+
nav: z.ZodObject<{
|
|
53
|
+
group: z.ZodString;
|
|
54
|
+
label: z.ZodString;
|
|
55
|
+
icon: z.ZodString;
|
|
56
|
+
}, z.core.$strict>;
|
|
57
|
+
routes: z.ZodArray<z.ZodString>;
|
|
58
|
+
widgets: z.ZodArray<z.ZodString>;
|
|
59
|
+
}, z.core.$strict>;
|
|
60
|
+
onboarding: z.ZodArray<z.ZodString>;
|
|
61
|
+
events: z.ZodArray<z.ZodString>;
|
|
62
|
+
apiScopes: z.ZodArray<z.ZodString>;
|
|
63
|
+
}, z.core.$strict>>;
|
|
64
|
+
}, z.core.$strict>>;
|
|
65
|
+
}, z.core.$strict>;
|
|
66
|
+
export declare const capabilityOperations: import("../op.ts").Operation[];
|
|
67
|
+
//# sourceMappingURL=capabilities.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capabilities.d.ts","sourceRoot":"","sources":["../../src/routes/capabilities.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,CAAC,EAAE,MAAM,WAAW,CAAC;AAE9B,eAAO,MAAM,YAAY,sCAAuC,CAAC;AAEjE,eAAO,MAAM,UAAU;;;;EAIrB,CAAC;AAEH,eAAO,MAAM,SAAS,aAG4E,CAAC;AAOnG,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;kBA0B3B,CAAC;AAEL,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAY4F,CAAC;AAElI,eAAO,MAAM,oBAAoB,gCA0BhC,CAAC"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Capabilities and the portal sections integrations register for them — architecture §7.2's
|
|
3
|
+
* capability manifest, approved by d47(i) without "brands are themes and hostnames". There is one
|
|
4
|
+
* portal, organised by capability; no manifest can carry a theme, a brand, a logo or a hostname.
|
|
5
|
+
*/
|
|
6
|
+
import { OrganisationId, words } from "../common.js";
|
|
7
|
+
import { MEMBER_NAME_PATTERN } from "../constitution/words.js";
|
|
8
|
+
import { operation } from "../op.js";
|
|
9
|
+
import { z } from "../zod.js";
|
|
10
|
+
export const CAPABILITIES = ["visits", "money", "work"];
|
|
11
|
+
export const Capability = z.enum(CAPABILITIES).meta({
|
|
12
|
+
id: "Capability",
|
|
13
|
+
description: "What an establishment does, never who powers it: visits (V) · money in and out (M) · work and jobs (W) (d50(b)1, d51). No client needs a member's name (PL-4 edge 7).",
|
|
14
|
+
});
|
|
15
|
+
export const SectionId = z
|
|
16
|
+
.string()
|
|
17
|
+
.regex(/^(visits|money|work)\.[a-z0-9]+(-[a-z0-9]+)*$/)
|
|
18
|
+
.meta({ id: "SectionId", description: "`<capability>.<name>`, e.g. money.every-rupee-report." });
|
|
19
|
+
const Label = words(60).refine((s) => !MEMBER_NAME_PATTERN.test(s), {
|
|
20
|
+
message: "A section is named for what it does, never for who powers it (PL-4 edge 7).",
|
|
21
|
+
params: { rule: "NO-MEMBER-NAME" },
|
|
22
|
+
});
|
|
23
|
+
export const CapabilityManifest = z
|
|
24
|
+
.object({
|
|
25
|
+
format: z.literal("indorania-capability-manifest/1"),
|
|
26
|
+
id: SectionId,
|
|
27
|
+
capability: Capability,
|
|
28
|
+
version: z.number().int().min(1),
|
|
29
|
+
permissions: z.array(z.string().regex(/^[a-z][a-z0-9-]*(\.[a-z][a-z0-9-]*)+$/)).meta({ description: "e.g. report.read" }),
|
|
30
|
+
settings: z.record(z.string(), z.unknown()).optional().meta({
|
|
31
|
+
description: "A JSON Schema (2020-12) for the section's settings. The portal generates the settings screen from it; nobody hand-builds one.",
|
|
32
|
+
}),
|
|
33
|
+
surfaces: z
|
|
34
|
+
.object({
|
|
35
|
+
nav: z.object({ group: Label, label: Label, icon: z.string().regex(/^[a-z0-9-]{1,40}$/) }).strict(),
|
|
36
|
+
routes: z.array(z.string().regex(/^\/[a-z0-9\-/[\]]*$/)),
|
|
37
|
+
widgets: z.array(z.string().regex(/^[a-z0-9-]+(\.[a-z0-9-]+)*$/)),
|
|
38
|
+
})
|
|
39
|
+
.strict(),
|
|
40
|
+
onboarding: z.array(z.string().regex(/^[a-z0-9-]+$/)),
|
|
41
|
+
events: z.array(z.string().regex(/^[a-z]+(\.[a-z-]+)+$/)).meta({ description: "Domain events the section emits, as webhook types." }),
|
|
42
|
+
apiScopes: z.array(z.string().regex(/^[a-z-]+:[a-z-]+$/)),
|
|
43
|
+
})
|
|
44
|
+
.strict()
|
|
45
|
+
.refine((m) => m.id.startsWith(`${m.capability}.`), { message: "A section's id starts with its capability.", path: ["id"] })
|
|
46
|
+
.meta({
|
|
47
|
+
id: "CapabilityManifest",
|
|
48
|
+
description: "One portal section, declared once. The portal composes itself from these; it never embeds a member's app (PL-10).",
|
|
49
|
+
});
|
|
50
|
+
export const OrganisationCapabilities = z
|
|
51
|
+
.object({
|
|
52
|
+
capabilities: z.array(z
|
|
53
|
+
.object({
|
|
54
|
+
capability: Capability,
|
|
55
|
+
sections: z.array(CapabilityManifest),
|
|
56
|
+
})
|
|
57
|
+
.strict()),
|
|
58
|
+
})
|
|
59
|
+
.strict()
|
|
60
|
+
.meta({ id: "OrganisationCapabilities", description: "What this organisation has switched on, and the sections each brings." });
|
|
61
|
+
export const capabilityOperations = [
|
|
62
|
+
operation({
|
|
63
|
+
operationId: "getCapabilities",
|
|
64
|
+
method: "get",
|
|
65
|
+
path: "/v1/organisations/{orgId}/capabilities",
|
|
66
|
+
tag: "capabilities",
|
|
67
|
+
summary: "Your organisation's capabilities and their portal sections",
|
|
68
|
+
auth: ["seat"],
|
|
69
|
+
pending: null,
|
|
70
|
+
collection: "An organisation's own capabilities, from which its portal composes itself.",
|
|
71
|
+
params: z.object({ orgId: OrganisationId }).strict(),
|
|
72
|
+
responses: { 200: { description: "The capabilities switched on.", schema: OrganisationCapabilities } },
|
|
73
|
+
}),
|
|
74
|
+
operation({
|
|
75
|
+
operationId: "putSection",
|
|
76
|
+
method: "put",
|
|
77
|
+
path: "/v1/integration/sections/{sectionId}",
|
|
78
|
+
tag: "capabilities",
|
|
79
|
+
summary: "Register or replace one portal section (portal-section registration)",
|
|
80
|
+
auth: ["integration"],
|
|
81
|
+
pending: null,
|
|
82
|
+
idempotency: "key",
|
|
83
|
+
params: z.object({ sectionId: SectionId }).strict(),
|
|
84
|
+
body: { schema: CapabilityManifest },
|
|
85
|
+
responses: { 200: { description: "Registered.", schema: CapabilityManifest } },
|
|
86
|
+
}),
|
|
87
|
+
];
|
|
88
|
+
//# sourceMappingURL=capabilities.js.map
|