@asturiu/v0-sdk 0.0.0-stage → 1.0.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 (239) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/LICENSE +202 -0
  3. package/NOTICE +5 -0
  4. package/README.md +82 -2
  5. package/contract/assertion-vectors.json +90 -0
  6. package/contract/schemas/branding.schema.json +46 -0
  7. package/contract/schemas/definitions.schema.json +376 -0
  8. package/contract/schemas/portal.schema.json +56 -0
  9. package/contract/tenant-api-routes.json +165 -0
  10. package/dist/branding.d.ts +131 -0
  11. package/dist/branding.d.ts.map +1 -0
  12. package/dist/branding.js +206 -0
  13. package/dist/branding.js.map +1 -0
  14. package/dist/changesets.d.ts +58 -0
  15. package/dist/changesets.d.ts.map +1 -0
  16. package/dist/changesets.js +18 -0
  17. package/dist/changesets.js.map +1 -0
  18. package/dist/cli/bin.d.ts +3 -0
  19. package/dist/cli/bin.d.ts.map +1 -0
  20. package/dist/cli/bin.js +12 -0
  21. package/dist/cli/bin.js.map +1 -0
  22. package/dist/cli/changesets.d.ts +14 -0
  23. package/dist/cli/changesets.d.ts.map +1 -0
  24. package/dist/cli/changesets.js +252 -0
  25. package/dist/cli/changesets.js.map +1 -0
  26. package/dist/cli/cli.d.ts +37 -0
  27. package/dist/cli/cli.d.ts.map +1 -0
  28. package/dist/cli/cli.js +415 -0
  29. package/dist/cli/cli.js.map +1 -0
  30. package/dist/cli/context.d.ts +147 -0
  31. package/dist/cli/context.d.ts.map +1 -0
  32. package/dist/cli/context.js +258 -0
  33. package/dist/cli/context.js.map +1 -0
  34. package/dist/cli/engine.d.ts +59 -0
  35. package/dist/cli/engine.d.ts.map +1 -0
  36. package/dist/cli/engine.js +85 -0
  37. package/dist/cli/engine.js.map +1 -0
  38. package/dist/cli/feedback.d.ts +40 -0
  39. package/dist/cli/feedback.d.ts.map +1 -0
  40. package/dist/cli/feedback.js +420 -0
  41. package/dist/cli/feedback.js.map +1 -0
  42. package/dist/cli/files.d.ts +83 -0
  43. package/dist/cli/files.d.ts.map +1 -0
  44. package/dist/cli/files.js +389 -0
  45. package/dist/cli/files.js.map +1 -0
  46. package/dist/cli/index.d.ts +8 -0
  47. package/dist/cli/index.d.ts.map +1 -0
  48. package/dist/cli/index.js +8 -0
  49. package/dist/cli/index.js.map +1 -0
  50. package/dist/cli/overview.d.ts +6 -0
  51. package/dist/cli/overview.d.ts.map +1 -0
  52. package/dist/cli/overview.js +379 -0
  53. package/dist/cli/overview.js.map +1 -0
  54. package/dist/cli/parts.d.ts +5 -0
  55. package/dist/cli/parts.d.ts.map +1 -0
  56. package/dist/cli/parts.js +414 -0
  57. package/dist/cli/parts.js.map +1 -0
  58. package/dist/cli/sources.d.ts +37 -0
  59. package/dist/cli/sources.d.ts.map +1 -0
  60. package/dist/cli/sources.js +91 -0
  61. package/dist/cli/sources.js.map +1 -0
  62. package/dist/cli/terminal.d.ts +135 -0
  63. package/dist/cli/terminal.d.ts.map +1 -0
  64. package/dist/cli/terminal.js +353 -0
  65. package/dist/cli/terminal.js.map +1 -0
  66. package/dist/cli/ui-page.d.ts +8 -0
  67. package/dist/cli/ui-page.d.ts.map +1 -0
  68. package/dist/cli/ui-page.js +216 -0
  69. package/dist/cli/ui-page.js.map +1 -0
  70. package/dist/cli/ui.d.ts +54 -0
  71. package/dist/cli/ui.d.ts.map +1 -0
  72. package/dist/cli/ui.js +251 -0
  73. package/dist/cli/ui.js.map +1 -0
  74. package/dist/client.d.ts +88 -0
  75. package/dist/client.d.ts.map +1 -0
  76. package/dist/client.js +165 -0
  77. package/dist/client.js.map +1 -0
  78. package/dist/contacts.d.ts +43 -0
  79. package/dist/contacts.d.ts.map +1 -0
  80. package/dist/contacts.js +46 -0
  81. package/dist/contacts.js.map +1 -0
  82. package/dist/definition-set.d.ts +731 -0
  83. package/dist/definition-set.d.ts.map +1 -0
  84. package/dist/definition-set.js +659 -0
  85. package/dist/definition-set.js.map +1 -0
  86. package/dist/definitions.d.ts +42 -0
  87. package/dist/definitions.d.ts.map +1 -0
  88. package/dist/definitions.js +154 -0
  89. package/dist/definitions.js.map +1 -0
  90. package/dist/enrolment.d.ts +9 -0
  91. package/dist/enrolment.d.ts.map +1 -0
  92. package/dist/enrolment.js +8 -0
  93. package/dist/enrolment.js.map +1 -0
  94. package/dist/fill.d.ts +73 -0
  95. package/dist/fill.d.ts.map +1 -0
  96. package/dist/fill.js +46 -0
  97. package/dist/fill.js.map +1 -0
  98. package/dist/index.d.ts +39 -0
  99. package/dist/index.d.ts.map +1 -0
  100. package/dist/index.js +39 -0
  101. package/dist/index.js.map +1 -0
  102. package/dist/notifications.d.ts +33 -0
  103. package/dist/notifications.d.ts.map +1 -0
  104. package/dist/notifications.js +36 -0
  105. package/dist/notifications.js.map +1 -0
  106. package/dist/oidc.d.ts +122 -0
  107. package/dist/oidc.d.ts.map +1 -0
  108. package/dist/oidc.js +150 -0
  109. package/dist/oidc.js.map +1 -0
  110. package/dist/overlay.d.ts +109 -0
  111. package/dist/overlay.d.ts.map +1 -0
  112. package/dist/overlay.js +58 -0
  113. package/dist/overlay.js.map +1 -0
  114. package/dist/passes.d.ts +95 -0
  115. package/dist/passes.d.ts.map +1 -0
  116. package/dist/passes.js +140 -0
  117. package/dist/passes.js.map +1 -0
  118. package/dist/portal-options.d.ts +65 -0
  119. package/dist/portal-options.d.ts.map +1 -0
  120. package/dist/portal-options.js +120 -0
  121. package/dist/portal-options.js.map +1 -0
  122. package/dist/reads.d.ts +41 -0
  123. package/dist/reads.d.ts.map +1 -0
  124. package/dist/reads.js +44 -0
  125. package/dist/reads.js.map +1 -0
  126. package/dist/recovery-words.d.ts +8 -0
  127. package/dist/recovery-words.d.ts.map +1 -0
  128. package/dist/recovery-words.js +136 -0
  129. package/dist/recovery-words.js.map +1 -0
  130. package/dist/recovery.d.ts +198 -0
  131. package/dist/recovery.d.ts.map +1 -0
  132. package/dist/recovery.js +112 -0
  133. package/dist/recovery.js.map +1 -0
  134. package/dist/reveal.d.ts +35 -0
  135. package/dist/reveal.d.ts.map +1 -0
  136. package/dist/reveal.js +66 -0
  137. package/dist/reveal.js.map +1 -0
  138. package/dist/seal.d.ts +15 -0
  139. package/dist/seal.d.ts.map +1 -0
  140. package/dist/seal.js +0 -0
  141. package/dist/seal.js.map +1 -0
  142. package/dist/session.d.ts +66 -0
  143. package/dist/session.d.ts.map +1 -0
  144. package/dist/session.js +61 -0
  145. package/dist/session.js.map +1 -0
  146. package/dist/signing-in-mark.d.ts +14 -0
  147. package/dist/signing-in-mark.d.ts.map +1 -0
  148. package/dist/signing-in-mark.js +24 -0
  149. package/dist/signing-in-mark.js.map +1 -0
  150. package/dist/signing-in.d.ts +22 -0
  151. package/dist/signing-in.d.ts.map +1 -0
  152. package/dist/signing-in.js +203 -0
  153. package/dist/signing-in.js.map +1 -0
  154. package/dist/tags.d.ts +96 -0
  155. package/dist/tags.d.ts.map +1 -0
  156. package/dist/tags.js +88 -0
  157. package/dist/tags.js.map +1 -0
  158. package/dist/tenant-subscription.d.ts +47 -0
  159. package/dist/tenant-subscription.d.ts.map +1 -0
  160. package/dist/tenant-subscription.js +7 -0
  161. package/dist/tenant-subscription.js.map +1 -0
  162. package/dist/testing/index.d.ts +125 -0
  163. package/dist/testing/index.d.ts.map +1 -0
  164. package/dist/testing/index.js +320 -0
  165. package/dist/testing/index.js.map +1 -0
  166. package/dist/theme.d.ts +237 -0
  167. package/dist/theme.d.ts.map +1 -0
  168. package/dist/theme.js +504 -0
  169. package/dist/theme.js.map +1 -0
  170. package/dist/tickets.d.ts +152 -0
  171. package/dist/tickets.d.ts.map +1 -0
  172. package/dist/tickets.js +65 -0
  173. package/dist/tickets.js.map +1 -0
  174. package/dist/tiers.d.ts +168 -0
  175. package/dist/tiers.d.ts.map +1 -0
  176. package/dist/tiers.js +341 -0
  177. package/dist/tiers.js.map +1 -0
  178. package/dist/types.d.ts +885 -0
  179. package/dist/types.d.ts.map +1 -0
  180. package/dist/types.js +12 -0
  181. package/dist/types.js.map +1 -0
  182. package/dist/urlid.d.ts +50 -0
  183. package/dist/urlid.d.ts.map +1 -0
  184. package/dist/urlid.js +78 -0
  185. package/dist/urlid.js.map +1 -0
  186. package/dist/version.d.ts +15 -0
  187. package/dist/version.d.ts.map +1 -0
  188. package/dist/version.js +15 -0
  189. package/dist/version.js.map +1 -0
  190. package/make/asturiu.mk +43 -0
  191. package/package.json +63 -4
  192. package/src/branding.ts +221 -0
  193. package/src/changesets.ts +61 -0
  194. package/src/cli/bin.ts +12 -0
  195. package/src/cli/changesets.ts +233 -0
  196. package/src/cli/cli.ts +425 -0
  197. package/src/cli/context.ts +299 -0
  198. package/src/cli/engine.ts +112 -0
  199. package/src/cli/feedback.ts +406 -0
  200. package/src/cli/files.ts +371 -0
  201. package/src/cli/index.ts +7 -0
  202. package/src/cli/overview.ts +343 -0
  203. package/src/cli/parts.ts +371 -0
  204. package/src/cli/sources.ts +111 -0
  205. package/src/cli/terminal.ts +384 -0
  206. package/src/cli/ui-page.ts +215 -0
  207. package/src/cli/ui.ts +266 -0
  208. package/src/client.ts +202 -0
  209. package/src/contacts.ts +61 -0
  210. package/src/definition-set.ts +965 -0
  211. package/src/definitions.ts +156 -0
  212. package/src/enrolment.ts +10 -0
  213. package/src/fill.ts +83 -0
  214. package/src/index.ts +38 -0
  215. package/src/notifications.ts +55 -0
  216. package/src/oidc.ts +199 -0
  217. package/src/overlay.ts +137 -0
  218. package/src/passes.ts +168 -0
  219. package/src/portal-options.ts +125 -0
  220. package/src/reads.ts +71 -0
  221. package/src/recovery-words.ts +137 -0
  222. package/src/recovery.ts +269 -0
  223. package/src/reveal.ts +72 -0
  224. package/src/seal.ts +0 -0
  225. package/src/session.ts +93 -0
  226. package/src/signing-in-mark.ts +23 -0
  227. package/src/signing-in.ts +213 -0
  228. package/src/tags.ts +146 -0
  229. package/src/tenant-subscription.ts +44 -0
  230. package/src/testing/index.ts +337 -0
  231. package/src/theme.ts +628 -0
  232. package/src/tickets.ts +195 -0
  233. package/src/tiers.ts +397 -0
  234. package/src/types.ts +847 -0
  235. package/src/urlid.ts +77 -0
  236. package/src/version.ts +15 -0
  237. package/templates/asturiu/branding.json +4 -0
  238. package/templates/asturiu/definitions.json +23 -0
  239. package/templates/asturiu/portal.json +16 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
package/dist/client.js ADDED
@@ -0,0 +1,165 @@
1
+ import { SESSION_HEADER } from "./session.js";
2
+ /**
3
+ * The Interface API as a Frontend consumes it (components/05-interface-api.md
4
+ * §Conventions): `X-Asturiu-Session` on every call except session exchange,
5
+ * `Idempotency-Key` on writes, `If-Match` for concurrency, cursors for
6
+ * collections, `application/problem+json` for errors — and a `404` that never
7
+ * distinguishes absent from forbidden.
8
+ *
9
+ * Runs wherever `fetch` exists: a Next.js server, an edge runtime, a browser
10
+ * talking to the Web UI's own `/api/v0` proxy.
11
+ */
12
+ export class InterfaceApiError extends Error {
13
+ status;
14
+ problem;
15
+ constructor(status, problem) {
16
+ super(problem.detail ?? problem.title ?? `HTTP ${status}`);
17
+ this.status = status;
18
+ this.problem = problem;
19
+ this.name = "InterfaceApiError";
20
+ }
21
+ get type() {
22
+ return this.problem.type ?? "";
23
+ }
24
+ get isUnauthorized() {
25
+ return this.status === 401;
26
+ }
27
+ get isNotFound() {
28
+ return this.status === 404;
29
+ }
30
+ get isPaused() {
31
+ return this.status === 503 && this.type.endsWith("platform-paused");
32
+ }
33
+ get isSuspended() {
34
+ return this.status === 403 && this.type.endsWith("account-suspended");
35
+ }
36
+ /** `POST /v0/sessions` for someone with no Customer yet, while the Tenant takes no new ones (ADR-044). */
37
+ get isEnrolmentClosed() {
38
+ return this.status === 403 && this.type.endsWith("enrolment-closed");
39
+ }
40
+ }
41
+ /** The ambient `fetch`, invoked on the global so it is valid as a method of any object. */
42
+ const globalFetch = (input, init) => globalThis.fetch(input, init);
43
+ function safeJson(text) {
44
+ if (!text)
45
+ return null;
46
+ try {
47
+ return JSON.parse(text);
48
+ }
49
+ catch {
50
+ return { raw: text };
51
+ }
52
+ }
53
+ export class InterfaceApiClient {
54
+ baseUrl;
55
+ prefix;
56
+ session;
57
+ ambientSession;
58
+ f;
59
+ timeoutMs;
60
+ constructor(opts) {
61
+ this.baseUrl = opts.baseUrl.replace(/\/+$/, "");
62
+ this.prefix = opts.prefix ?? "/v0";
63
+ this.session = opts.session ?? null;
64
+ this.ambientSession = opts.ambientSession ?? false;
65
+ // Never store the bare global `fetch` and call it as `this.f(...)`: browsers
66
+ // then see `this === InterfaceApiClient` and throw
67
+ // "Failed to execute 'fetch' on 'Window': Illegal invocation" (Node is
68
+ // lenient, so only the Web UI breaks). Always call through `globalFetch`.
69
+ this.f = opts.fetch ?? globalFetch;
70
+ this.timeoutMs = opts.timeoutMs ?? 30000;
71
+ }
72
+ /** The same client acting for another (or no) session. */
73
+ withSession(session) {
74
+ return new InterfaceApiClient({ baseUrl: this.baseUrl, prefix: this.prefix, session, ambientSession: this.ambientSession, fetch: this.f, timeoutMs: this.timeoutMs });
75
+ }
76
+ url(path, query) {
77
+ const u = new URL(`${this.baseUrl}${this.prefix}${path.startsWith("/") ? path : `/${path}`}`);
78
+ for (const [k, v] of Object.entries(query ?? {}))
79
+ if (v !== undefined && v !== null && v !== "")
80
+ u.searchParams.set(k, String(v));
81
+ return u.toString();
82
+ }
83
+ async call(method, path, opts = {}) {
84
+ const headers = { accept: "application/json, application/problem+json, */*" };
85
+ for (const [k, v] of Object.entries(opts.headers ?? {}))
86
+ if (v !== undefined)
87
+ headers[k.toLowerCase()] = v;
88
+ if (opts.session !== false && !this.ambientSession) {
89
+ if (!this.session)
90
+ throw new InterfaceApiError(401, { type: "urn:asturiu:problem:unauthorized", title: "Unauthorized", status: 401, detail: "no session" });
91
+ headers[SESSION_HEADER] = this.session;
92
+ }
93
+ let body;
94
+ if (opts.raw !== undefined) {
95
+ body = opts.raw;
96
+ headers["content-type"] = opts.contentType ?? "application/octet-stream";
97
+ }
98
+ else if (opts.body !== undefined) {
99
+ headers["content-type"] = "application/json";
100
+ body = JSON.stringify(opts.body);
101
+ }
102
+ if (["POST", "PUT"].includes(method) && opts.idempotencyKey !== false && !headers["idempotency-key"])
103
+ headers["idempotency-key"] = opts.idempotencyKey ?? crypto.randomUUID();
104
+ if (opts.ifMatch !== undefined)
105
+ headers["if-match"] = String(opts.ifMatch);
106
+ const res = await this.f(this.url(path, opts.query), { method, headers, body, signal: opts.signal ?? AbortSignal.timeout(this.timeoutMs), cache: "no-store" });
107
+ const text = await res.text();
108
+ const json = safeJson(text);
109
+ if (!res.ok) {
110
+ const problem = json && typeof json === "object" && "status" in json ? json : { type: "urn:asturiu:problem:http", title: res.statusText || "Error", status: res.status, detail: typeof json === "object" && json && "raw" in json ? String(json.raw).slice(0, 300) : undefined };
111
+ throw new InterfaceApiError(res.status, problem);
112
+ }
113
+ return { status: res.status, body: json, headers: res.headers };
114
+ }
115
+ /** Binary download (Attachment content). */
116
+ async download(path, opts = {}) {
117
+ const headers = {};
118
+ if (opts.session !== false && !this.ambientSession) {
119
+ if (!this.session)
120
+ throw new InterfaceApiError(401, { type: "urn:asturiu:problem:unauthorized", title: "Unauthorized", status: 401 });
121
+ headers[SESSION_HEADER] = this.session;
122
+ }
123
+ const res = await this.f(this.url(path, opts.query), { method: "GET", headers, signal: opts.signal ?? AbortSignal.timeout(this.timeoutMs), cache: "no-store" });
124
+ if (!res.ok)
125
+ throw new InterfaceApiError(res.status, safeJson(await res.text()) ?? { type: "urn:asturiu:problem:http", title: "Error", status: res.status });
126
+ const cd = res.headers.get("content-disposition") ?? "";
127
+ const m = /filename="?([^";]+)"?/.exec(cd);
128
+ return { status: res.status, bytes: await res.arrayBuffer(), contentType: res.headers.get("content-type") ?? "application/octet-stream", filename: m?.[1] };
129
+ }
130
+ get(path, query, opts = {}) {
131
+ return this.call("GET", path, { ...opts, query }).then((r) => r.body);
132
+ }
133
+ post(path, body, opts = {}) {
134
+ return this.call("POST", path, { ...opts, body }).then((r) => r.body);
135
+ }
136
+ put(path, body, opts = {}) {
137
+ return this.call("PUT", path, { ...opts, body }).then((r) => r.body);
138
+ }
139
+ patch(path, body, opts = {}) {
140
+ return this.call("PATCH", path, { ...opts, body }).then((r) => r.body);
141
+ }
142
+ delete(path, opts = {}) {
143
+ return this.call("DELETE", path, opts).then((r) => r.body);
144
+ }
145
+ /** Walk every page of a cursor-paginated collection. */
146
+ async all(path, query = {}, limit = 100) {
147
+ const out = [];
148
+ let cursor = null;
149
+ do {
150
+ const page = await this.get(path, { ...query, limit, cursor: cursor ?? undefined });
151
+ out.push(...page.items);
152
+ cursor = page.next_cursor;
153
+ } while (cursor);
154
+ return out;
155
+ }
156
+ }
157
+ /** Every caller-facing error becomes a problem shape, so UIs render one thing. */
158
+ export function toProblem(err) {
159
+ if (err instanceof InterfaceApiError)
160
+ return err.problem;
161
+ if (err instanceof Error)
162
+ return { type: "urn:asturiu:problem:client", title: err.name, status: 0, detail: err.message };
163
+ return { type: "urn:asturiu:problem:client", title: "Error", status: 0, detail: String(err) };
164
+ }
165
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Contacts, handles and disclosure (ADR-024). Pure vocabulary shared by the
3
+ * Engine, the CLI and every frontend: the pair-state function is the one
4
+ * place the two rows of a Contact are read into one answer, so it must be the
5
+ * same everywhere. Dependency-free on purpose.
6
+ */
7
+ /** A holder's own decision about one Contact, stored on its row. */
8
+ export declare const CONTACT_INTENTS: readonly ["accepted", "incoming", "blocked"];
9
+ export type ContactIntent = (typeof CONTACT_INTENTS)[number];
10
+ /** What one side sees, derived from both rows and never stored. */
11
+ export declare const CONTACT_STATES: readonly ["active", "pending", "incoming", "blocked", "removed"];
12
+ export type ContactState = (typeof CONTACT_STATES)[number];
13
+ /** How the Contact came to exist. */
14
+ export declare const CONTACT_ORIGINS: readonly ["request", "grant", "transfer", "recovery"];
15
+ export type ContactOrigin = (typeof CONTACT_ORIGINS)[number];
16
+ /** The profile fields a holder may disclose to one Contact. The handle is always visible to an active Contact and is not on this list. */
17
+ export declare const DISCLOSABLE_FIELDS: readonly ["display_name", "name", "email", "phone"];
18
+ export type DisclosableField = (typeof DISCLOSABLE_FIELDS)[number];
19
+ /**
20
+ * The counterpart row as the holder's side sees it: an intent when the row
21
+ * is readable, `missing` when no counterpart row was ever linked (an external
22
+ * Principal not redeemed yet), `removed` when the linked row is gone (the
23
+ * counterpart deleted the Contact, or the Customer was deleted).
24
+ */
25
+ export type CounterpartIntent = ContactIntent | "missing" | "removed";
26
+ /**
27
+ * The state one holder sees. Order matters:
28
+ *
29
+ * - my own block is always shown to me as `blocked`;
30
+ * - a counterpart that is gone is `removed`, whatever I had decided;
31
+ * - a request I have not answered is `incoming`;
32
+ * - both accepted is `active`;
33
+ * - everything else — the counterpart has not answered, has declined
34
+ * silently, or has blocked me — reads `pending`. A block is never visible
35
+ * to the blocked side.
36
+ */
37
+ export declare function contactState(mine: ContactIntent, theirs: CounterpartIntent): ContactState;
38
+ /** Platform-wide handle (ADR-024): lowercase, 3–30 characters, starts with a letter or digit. */
39
+ export declare const HANDLE_PATTERN: RegExp;
40
+ export declare function isHandle(value: unknown): value is string;
41
+ /** Normalise what a person typed as a handle: trim, lower-case, strip a leading `@`. Validation is `isHandle`. */
42
+ export declare function normalizeHandle(value: string): string;
43
+ //# sourceMappingURL=contacts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contacts.d.ts","sourceRoot":"","sources":["../src/contacts.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,oEAAoE;AACpE,eAAO,MAAM,eAAe,8CAA+C,CAAC;AAC5E,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;AAE7D,mEAAmE;AACnE,eAAO,MAAM,cAAc,kEAAmE,CAAC;AAC/F,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAE3D,qCAAqC;AACrC,eAAO,MAAM,eAAe,uDAAwD,CAAC;AACrF,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;AAE7D,0IAA0I;AAC1I,eAAO,MAAM,kBAAkB,qDAAsD,CAAC;AACtF,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEnE;;;;;GAKG;AACH,MAAM,MAAM,iBAAiB,GAAG,aAAa,GAAG,SAAS,GAAG,SAAS,CAAC;AAEtE;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,iBAAiB,GAAG,YAAY,CAMzF;AAED,iGAAiG;AACjG,eAAO,MAAM,cAAc,QAAgC,CAAC;AAE5D,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAExD;AAED,kHAAkH;AAClH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAErD"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Contacts, handles and disclosure (ADR-024). Pure vocabulary shared by the
3
+ * Engine, the CLI and every frontend: the pair-state function is the one
4
+ * place the two rows of a Contact are read into one answer, so it must be the
5
+ * same everywhere. Dependency-free on purpose.
6
+ */
7
+ /** A holder's own decision about one Contact, stored on its row. */
8
+ export const CONTACT_INTENTS = ["accepted", "incoming", "blocked"];
9
+ /** What one side sees, derived from both rows and never stored. */
10
+ export const CONTACT_STATES = ["active", "pending", "incoming", "blocked", "removed"];
11
+ /** How the Contact came to exist. */
12
+ export const CONTACT_ORIGINS = ["request", "grant", "transfer", "recovery"];
13
+ /** The profile fields a holder may disclose to one Contact. The handle is always visible to an active Contact and is not on this list. */
14
+ export const DISCLOSABLE_FIELDS = ["display_name", "name", "email", "phone"];
15
+ /**
16
+ * The state one holder sees. Order matters:
17
+ *
18
+ * - my own block is always shown to me as `blocked`;
19
+ * - a counterpart that is gone is `removed`, whatever I had decided;
20
+ * - a request I have not answered is `incoming`;
21
+ * - both accepted is `active`;
22
+ * - everything else — the counterpart has not answered, has declined
23
+ * silently, or has blocked me — reads `pending`. A block is never visible
24
+ * to the blocked side.
25
+ */
26
+ export function contactState(mine, theirs) {
27
+ if (mine === "blocked")
28
+ return "blocked";
29
+ if (theirs === "removed")
30
+ return "removed";
31
+ if (mine === "incoming")
32
+ return "incoming";
33
+ if (theirs === "accepted")
34
+ return "active";
35
+ return "pending";
36
+ }
37
+ /** Platform-wide handle (ADR-024): lowercase, 3–30 characters, starts with a letter or digit. */
38
+ export const HANDLE_PATTERN = /^[a-z0-9][a-z0-9._-]{2,29}$/;
39
+ export function isHandle(value) {
40
+ return typeof value === "string" && HANDLE_PATTERN.test(value);
41
+ }
42
+ /** Normalise what a person typed as a handle: trim, lower-case, strip a leading `@`. Validation is `isHandle`. */
43
+ export function normalizeHandle(value) {
44
+ return value.trim().replace(/^@/, "").toLowerCase();
45
+ }
46
+ //# sourceMappingURL=contacts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contacts.js","sourceRoot":"","sources":["../src/contacts.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,oEAAoE;AACpE,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,UAAU,EAAE,UAAU,EAAE,SAAS,CAAU,CAAC;AAG5E,mEAAmE;AACnE,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,QAAQ,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,CAAU,CAAC;AAG/F,qCAAqC;AACrC,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,CAAU,CAAC;AAGrF,0IAA0I;AAC1I,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,cAAc,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAU,CAAC;AAWtF;;;;;;;;;;GAUG;AACH,MAAM,UAAU,YAAY,CAAC,IAAmB,EAAE,MAAyB;IACzE,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IACzC,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC3C,IAAI,IAAI,KAAK,UAAU;QAAE,OAAO,UAAU,CAAC;IAC3C,IAAI,MAAM,KAAK,UAAU;QAAE,OAAO,QAAQ,CAAC;IAC3C,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,iGAAiG;AACjG,MAAM,CAAC,MAAM,cAAc,GAAG,6BAA6B,CAAC;AAE5D,MAAM,UAAU,QAAQ,CAAC,KAAc;IACrC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACjE,CAAC;AAED,kHAAkH;AAClH,MAAM,UAAU,eAAe,CAAC,KAAa;IAC3C,OAAO,KAAK,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;AACtD,CAAC"}