@formancy/server-core 0.4.0 → 0.6.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 CHANGED
@@ -27,19 +27,30 @@ server gets argon2id and a CSPRNG.
27
27
  ## Use
28
28
 
29
29
  ```ts
30
- import { publishForm, createSubmission, can } from '@formancy/server-core'
30
+ import { publishForm, formToFill, createSubmission, can } from '@formancy/server-core'
31
31
 
32
32
  const published = await publishForm(deps, { path: 'contact-us', schema })
33
33
  // publishForm is the save gate: structural validation, then the engine's own
34
34
  // compile — a form that could loop is refused here and never persisted.
35
35
 
36
+ // What a respondent is handed: the current version, and the token its response is
37
+ // sent back with, so that a response sent twice is stored once.
38
+ const form = await formToFill(deps, 'contact-us')
39
+
36
40
  const outcome = await createSubmission(deps, {
37
41
  path: 'contact-us',
38
- declaredSchemaHash: published.schemaHash,
42
+ declaredSchemaHash: form.schemaHash,
43
+ token: form.submissionToken,
39
44
  data: payload,
40
45
  })
46
+ // The same token again: { ok: false, kind: 'token_spent', id }, and nothing stored.
41
47
  ```
42
48
 
49
+ `publishForm`, `keepExamples` and `createSubmission` write their audit row inside
50
+ the transaction of what they record. Give them a `requestId` and the row names
51
+ that request, so it can be read beside a request log — `@formancy/server` passes
52
+ Fastify's request id. Without one, the row names none.
53
+
43
54
  Authorization is one readable table (`can(actor, action)`), deliberately not
44
55
  Postgres row-level security: RLS couples the application to per-request database
45
56
  roles and hides authorization from the test suite.
package/dist/index.d.mts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { CHALLENGE_TTL_SECONDS, Challenge, DEFAULT_MAX_NUMBER, Solution, VerifyOutcome, decodeSolution, encodeSolution, hashOf, mintChallenge, solveChallenge, verifySolution } from "@formancy/challenge";
2
+ import { CapabilitySource, Check, Scenario } from "@formancy/core";
2
3
  import { Change, FormSchema } from "@formancy/spec";
3
- import { CapabilitySource, Check } from "@formancy/core";
4
4
  import { SchemaError } from "@formancy/spec/validate";
5
5
  //#region src/options-membership.d.ts
6
6
  /**
@@ -220,8 +220,37 @@ interface FileRecord {
220
220
  createdAt: string;
221
221
  /** The submission that claimed it, or null. One file, one submission. */
222
222
  submissionId: string | null;
223
+ /**
224
+ * Until when one request holds the right to receive this file's bytes, or null when
225
+ * none does. Not a fourth state: the file is still `offered` while it is received, and
226
+ * a lease that has run out is no lease. See `leaseFile`.
227
+ */
228
+ receivingUntil: string | null;
229
+ }
230
+ /**
231
+ * A form's examples, and the fictional sample every one of them starts from — the pair the
232
+ * starter templates carry as `*.scenarios.json` and `*.sample.json`
233
+ * ([0166](../../../docs/decisions/0166-a-deployment-keeps-a-forms-examples-and-runs-them-at-publish.md)).
234
+ *
235
+ * Beside the form and not inside a version. A published version is immutable
236
+ * ([0025](../../../docs/decisions/0025-immutability-in-the-database.md)), and examples change
237
+ * while the form does not: written into a version, every example added would mint one. One
238
+ * record per form, replaced whole, because the scenario panes hand back the whole list.
239
+ */
240
+ interface ExamplesRecord {
241
+ formId: string;
242
+ scenarios: readonly Scenario[];
243
+ /** Where every example starts, or null when none was kept. */
244
+ sample: Readonly<Record<string, unknown>> | null;
245
+ updatedAt: string;
223
246
  }
224
247
  interface Storage {
248
+ /**
249
+ * The form at this path, or `undefined` for a path no form has — one holding a character this
250
+ * storage cannot keep included, such as a NUL in PostgreSQL's `text`. It arrives from a URL, as
251
+ * anybody wrote it, so it is an unknown form and never an error. `getDraft`, `getUserByEmail`
252
+ * and `findApiKeysByPrefix` find none the same way: what they look up arrives from a request too.
253
+ */
225
254
  getFormByPath(path: string): Promise<FormRecord | undefined>;
226
255
  listForms(): Promise<FormRecord[]>;
227
256
  createForm(record: FormRecord): Promise<void>;
@@ -252,6 +281,17 @@ interface Storage {
252
281
  audit?: AuditEntry;
253
282
  }): Promise<void>;
254
283
  getVersionById(id: string): Promise<FormVersionRecord | undefined>;
284
+ /** A form's examples, or undefined when none were ever kept for it. */
285
+ getExamples(formId: string): Promise<ExamplesRecord | undefined>;
286
+ /**
287
+ * Replace a form's examples and sample, with the audit row, in ONE commit — as a publish
288
+ * carries its own: a change that rolled back must leave nothing saying it happened.
289
+ *
290
+ * The form must exist; the PostgreSQL storage has the database refuse one that does not.
291
+ * Nothing here reads the examples: whether they are examples is the use-case's question,
292
+ * asked before this is called, and again of what `getExamples` hands back.
293
+ */
294
+ keepExamples(record: ExamplesRecord, audit?: AuditEntry): Promise<void>;
255
295
  findVersionByHash(formId: string, schemaHash: string): Promise<FormVersionRecord | undefined>;
256
296
  latestVersionNumber(formId: string): Promise<number>;
257
297
  /**
@@ -269,8 +309,23 @@ interface Storage {
269
309
  * prevents — a webhook fired for a rolled-back submission, a stored
270
310
  * submission nothing was sent about, an accepted submission whose files the
271
311
  * collector deletes — are the ones a self-hoster cannot debug.
312
+ *
313
+ * Returns false, and writes NOTHING — no delivery, no claim, no audit row — when a
314
+ * submission with `record.id` is already stored. The id is the one a response's token
315
+ * names, so that is the same response sent twice
316
+ * ([0169](../../../docs/decisions/0169-a-response-is-stored-once.md)). ATOMIC, as
317
+ * `spendChallenge` is and for its reason: two sends of one response both pass every check
318
+ * made before this, and only the storage can decide which is stored.
319
+ */
320
+ insertSubmission(record: SubmissionRecord, deliveries?: readonly DeliveryRecord[], claimFileIds?: readonly string[], audit?: AuditEntry): Promise<boolean>;
321
+ /**
322
+ * Whether a submission with this id is stored.
323
+ *
324
+ * Asked before the replay, so a response sent again is told it was sent — rather than that
325
+ * the files it names are unknown, which is what the claim would say of files the first send
326
+ * already took. `insertSubmission` still decides: two sends at once both find nothing here.
272
327
  */
273
- insertSubmission(record: SubmissionRecord, deliveries?: readonly DeliveryRecord[], claimFileIds?: readonly string[], audit?: AuditEntry): Promise<void>;
328
+ hasSubmission(id: string): Promise<boolean>;
274
329
  /**
275
330
  * Append one audit row.
276
331
  *
@@ -305,8 +360,42 @@ interface Storage {
305
360
  /** Drop spent challenges that can no longer be replayed anyway. */
306
361
  forgetExpiredChallenges(beforeIso: string): Promise<number>;
307
362
  insertFile(record: FileRecord): Promise<void>;
363
+ /**
364
+ * The file with this id, or `undefined` for an id no file has — one in no shape this storage's
365
+ * ids take included. It arrives from a URL and from a response, as anybody wrote it, so it is an
366
+ * unknown file and never an error.
367
+ */
308
368
  getFile(id: string): Promise<FileRecord | undefined>;
309
- updateFile(record: FileRecord): Promise<void>;
369
+ /**
370
+ * Take the right to receive an `offered` file's bytes, until `untilIso`.
371
+ *
372
+ * Returns false when the file is not `offered`, or another request holds a lease that
373
+ * has not run out at `nowIso`. ATOMIC, as `spendChallenge` is and for its reason: two
374
+ * requests carrying bytes for one file both pass every check made before this, and only
375
+ * the storage can decide which of them receives. A lease that reads and then writes hands
376
+ * the file to both, and the second writes its bytes over the first's.
377
+ *
378
+ * `untilIso` is also the lease's name, handed back to `settleFile` and `releaseFile`. No
379
+ * two requests can hold one at once: a lease is taken only once the last has run out,
380
+ * so the next always runs out later.
381
+ */
382
+ leaseFile(id: string, nowIso: string, untilIso: string): Promise<boolean>;
383
+ /**
384
+ * The bytes are kept: `stored`, and the lease cleared — only while the file is `offered`
385
+ * and the lease named `untilIso` still holds it. Returns false and changes nothing
386
+ * otherwise.
387
+ *
388
+ * It sets the state and nothing else. Its predecessor wrote back the whole record the
389
+ * request had read before its scan, so a request that outlasted a faster one put a
390
+ * claimed file back to `stored` with no submission, for the collector to delete.
391
+ */
392
+ settleFile(id: string, untilIso: string): Promise<boolean>;
393
+ /**
394
+ * Give the lease back without keeping anything, so the retry a refusal invites is not
395
+ * refused as busy. Only the lease named `untilIso`: a request that outlasted its own
396
+ * must not free the one that took over.
397
+ */
398
+ releaseFile(id: string, untilIso: string): Promise<boolean>;
310
399
  /** Every file in a state other than `claimed`, created before `beforeIso`. */
311
400
  abandonedFiles(beforeIso: string): Promise<FileRecord[]>;
312
401
  deleteFiles(ids: readonly string[]): Promise<void>;
@@ -323,6 +412,7 @@ interface Storage {
323
412
  * a table nobody looks at, which is the same as not having it.
324
413
  */
325
414
  deadDeliveries(limit: number): Promise<DeliveryRecord[]>;
415
+ /** As `getFile`: `undefined` for an id no delivery has, whatever its shape, since it arrives from a URL. */
326
416
  getDelivery(id: string): Promise<DeliveryRecord | undefined>;
327
417
  /** Oldest first, only those due. */
328
418
  claimDueDeliveries(nowIso: string, limit: number): Promise<DeliveryRecord[]>;
@@ -438,7 +528,7 @@ export declare function can(actor: Actor, action: Action): boolean;
438
528
  * Closed so a new route cannot invent its own spelling: an audit log where one event is
439
529
  * called two things is one nobody can query.
440
530
  */
441
- export declare const AUDIT_ACTIONS: readonly ["auth.login", "auth.login.failed", "form.published", "form.access.changed", "submission.created", "submission.read", "submission.exported", "file.downloaded", "user.created", "apiKey.created", "apiKey.revoked", "delivery.replayed"];
531
+ export declare const AUDIT_ACTIONS: readonly ["auth.login", "auth.login.failed", "form.published", "form.access.changed", "form.examples.changed", "submission.created", "submission.read", "submission.exported", "file.downloaded", "user.created", "apiKey.created", "apiKey.revoked", "delivery.replayed", "model.asked"];
442
532
  type AuditAction = (typeof AUDIT_ACTIONS)[number];
443
533
  interface AuditEntry {
444
534
  readonly id: string;
@@ -458,7 +548,9 @@ interface AuditEntry {
458
548
  readonly subject?: string;
459
549
  /**
460
550
  * The request it happened in, so an export and the rows it returned can be
461
- * tied together later.
551
+ * tied together later — and a row to the line a server's request log wrote
552
+ * for that request. A use-case that writes its row inside its transaction
553
+ * takes the id in its input, and names it when it is given one.
462
554
  */
463
555
  readonly requestId?: string;
464
556
  /** Identifiers and counts. Never a submission's answers. */
@@ -775,13 +867,16 @@ interface ServerDeps {
775
867
  /** The clock/randomness the ENGINE sees during replay. */
776
868
  capabilities: CapabilitySource;
777
869
  /**
778
- * Signs the token that proves somebody started a draft.
870
+ * Signs the keys the public plane hands out: the one that proves somebody started a
871
+ * draft, and the token a response is sent with so that it is stored once (0169).
779
872
  *
780
873
  * The public plane is anonymous, so a draft has no account behind it — which
781
874
  * is exactly why it needs a secret of its own. The host's own signing key is
782
875
  * reused rather than a second one being configured: a draft token is a
783
876
  * server-signed bearer token, which is what that key is already for, and an
784
877
  * optional secret would mean drafts are unprotected whenever nobody set it.
878
+ * Named for the first of the two; renaming it would break every host that builds
879
+ * these deps, for a word.
785
880
  */
786
881
  draftSecret: string;
787
882
  /**
@@ -822,48 +917,6 @@ interface ResolvedForm {
822
917
  schemaHash: string;
823
918
  }
824
919
  export declare function resolveForm(deps: ServerDeps, path: string): Promise<ResolvedForm | undefined>;
825
- type SubmissionOutcome = {
826
- ok: true;
827
- id: string;
828
- canonicalData: unknown;
829
- } | {
830
- ok: false;
831
- kind: 'unknown_form';
832
- } | {
833
- ok: false;
834
- kind: 'version_changed';
835
- current?: ResolvedForm;
836
- } | {
837
- ok: false;
838
- kind: 'invalid';
839
- errors: Record<string, string[]>;
840
- } |
841
- /** The caller may not submit this form: not public, or not from this origin. */
842
- {
843
- ok: false;
844
- kind: 'forbidden';
845
- } |
846
- /**
847
- * A source that should have vouched for an answer could not.
848
- *
849
- * Failed closed and never accepted unchecked: a bogus value that is stored is
850
- * undetectable afterwards, while a refusal is retryable and the draft still holds
851
- * the answers.
852
- */
853
- {
854
- ok: false;
855
- kind: 'source_unavailable';
856
- source: string;
857
- };
858
- /**
859
- * Accept one submission: resolve the version the client says it rendered,
860
- * replay the engine over the submitted data, and store the CANONICAL result.
861
- *
862
- * The replay is the whole point. Computed values are recomputed and overwrite
863
- * whatever arrived; visibility is evaluated server-side and hidden branches
864
- * are stripped, so a client cannot smuggle data by lying about what was shown.
865
- * Client validation is UX; this is truth.
866
- */
867
920
  /**
868
921
  * Change who may submit a form, and from where.
869
922
  *
@@ -878,14 +931,6 @@ export declare function setFormAccess(deps: ServerDeps, input: {
878
931
  }): Promise<{
879
932
  ok: boolean;
880
933
  }>;
881
- export declare function createSubmission(deps: ServerDeps, input: {
882
- path: string;
883
- declaredSchemaHash: string;
884
- data: unknown;
885
- /** Defaults to anonymous: the caller must prove otherwise, not the reverse. */
886
- actor?: 'anonymous' | 'authenticated';
887
- origin?: string;
888
- }): Promise<SubmissionOutcome>;
889
934
  interface ListedSubmission {
890
935
  id: string;
891
936
  version: number;
@@ -913,13 +958,21 @@ export declare function exportCsv(deps: ServerDeps, path: string): Promise<strin
913
958
  * The id is the server's because an id a caller supplies is an id a caller can
914
959
  * enumerate — and enumerating them was enough to read other people's
915
960
  * part-filled answers.
961
+ *
962
+ * A draft is one response, so it comes with the token that response is sent with, naming the
963
+ * draft's own id ([0169](../../../docs/decisions/0169-a-response-is-stored-once.md)). Resuming
964
+ * hands back the same one, so a response whose answer was lost and is sent again after a reload
965
+ * is refused as already sent rather than stored twice.
916
966
  */
917
967
  export declare function startDraft(deps: ServerDeps, input: {
918
968
  path: string;
919
969
  }): Promise<{
920
970
  draftId: string;
921
971
  token: string;
972
+ submissionToken: string;
922
973
  } | undefined>;
974
+ /** Save (or re-save) a partial form, bound to the CURRENT version. Undefined
975
+ * for an unknown form. */
923
976
  export declare function saveDraft(deps: ServerDeps, input: {
924
977
  path: string;
925
978
  draftId: string;
@@ -941,6 +994,8 @@ type ResumeOutcome = {
941
994
  data: unknown;
942
995
  /** Present when the rebind lost something; absent for a silent rebind. */
943
996
  migration?: DraftMigration;
997
+ /** What the response is sent with: the same on every resume, naming the draft's id. */
998
+ submissionToken: string;
944
999
  } | {
945
1000
  /** The schema changed in a way no automatic rebind survives: the draft
946
1001
  * comes back against ITS OWN version, and the caller offers a restart. */
@@ -983,6 +1038,110 @@ interface ListedVersion {
983
1038
  * view rendering fifty full schemas would be its own denial of service. */
984
1039
  export declare function listVersions(deps: ServerDeps, path: string): Promise<ListedVersion[] | undefined>;
985
1040
  //#endregion
1041
+ //#region src/submitting.d.ts
1042
+ /**
1043
+ * Submitting a form: what a respondent is handed, the replay, and what is stored.
1044
+ *
1045
+ * Its own file because `use-cases.ts` named it as the next family to leave when its size
1046
+ * budget refused growth, and the submission is what grew.
1047
+ */
1048
+ type SubmissionOutcome = {
1049
+ ok: true;
1050
+ id: string;
1051
+ canonicalData: unknown;
1052
+ } | {
1053
+ ok: false;
1054
+ kind: 'unknown_form';
1055
+ } | {
1056
+ ok: false;
1057
+ kind: 'version_changed';
1058
+ current?: ResolvedForm;
1059
+ } | {
1060
+ ok: false;
1061
+ kind: 'invalid';
1062
+ errors: Record<string, string[]>;
1063
+ } |
1064
+ /** The caller may not submit this form: not public, or not from this origin. */
1065
+ {
1066
+ ok: false;
1067
+ kind: 'forbidden';
1068
+ } |
1069
+ /**
1070
+ * A source that should have vouched for an answer could not.
1071
+ *
1072
+ * Failed closed and never accepted unchecked: a bogus value that is stored is
1073
+ * undetectable afterwards, while a refusal is retryable and the draft still holds
1074
+ * the answers.
1075
+ */
1076
+ {
1077
+ ok: false;
1078
+ kind: 'source_unavailable';
1079
+ source: string;
1080
+ } |
1081
+ /** An anonymous response arrived without the token its form was handed out with. */
1082
+ {
1083
+ ok: false;
1084
+ kind: 'token_required';
1085
+ } |
1086
+ /**
1087
+ * A token this server did not sign for this form: forged, another form's, or signed under
1088
+ * a key the deployment no longer has. Loading the form again hands out a good one.
1089
+ */
1090
+ {
1091
+ ok: false;
1092
+ kind: 'token_invalid';
1093
+ } |
1094
+ /** The response this token names is already stored, as `id`; nothing was stored again. */
1095
+ {
1096
+ ok: false;
1097
+ kind: 'token_spent';
1098
+ id: string;
1099
+ };
1100
+ /** A published form as a respondent is handed it: its current version, and what to send it with. */
1101
+ interface FormToFill extends ResolvedForm {
1102
+ /** Names the id the response will be stored under, signed for this form (0169). */
1103
+ submissionToken: string;
1104
+ }
1105
+ /**
1106
+ * The form a respondent fills in, with the token their response is sent with.
1107
+ *
1108
+ * A fresh id on every call, because every reading is a response that might be sent: two
1109
+ * people handed one token would find the second refused as already sent. Minting writes
1110
+ * nothing — an HMAC over the form and the id — so handing one to everybody who reads the form
1111
+ * costs this server a hash and fills no table
1112
+ * ([0169](../../../docs/decisions/0169-a-response-is-stored-once.md)).
1113
+ */
1114
+ export declare function formToFill(deps: ServerDeps, path: string): Promise<FormToFill | undefined>;
1115
+ /**
1116
+ * Accept one submission: resolve the version the client says it rendered,
1117
+ * replay the engine over the submitted data, and store the CANONICAL result.
1118
+ *
1119
+ * The replay is the whole point. Computed values are recomputed and overwrite
1120
+ * whatever arrived; visibility is evaluated server-side and hidden branches
1121
+ * are stripped, so a client cannot smuggle data by lying about what was shown.
1122
+ * Client validation is UX; this is truth.
1123
+ *
1124
+ * And it is stored once. A response is stored under the id its token names, and the storage
1125
+ * refuses that id twice, so the same response sent again — a retry after an answer that never
1126
+ * arrived, a replay — is told it was sent rather than stored as somebody else
1127
+ * ([0169](../../../docs/decisions/0169-a-response-is-stored-once.md)).
1128
+ */
1129
+ export declare function createSubmission(deps: ServerDeps, input: {
1130
+ path: string;
1131
+ declaredSchemaHash: string;
1132
+ data: unknown;
1133
+ /** Defaults to anonymous: the caller must prove otherwise, not the reverse. */
1134
+ actor?: 'anonymous' | 'authenticated';
1135
+ origin?: string;
1136
+ requestId?: string;
1137
+ /**
1138
+ * The token the form was handed out with. Required of an anonymous response. A signed-in
1139
+ * one may leave it out and is stored under a fresh id, as before; one it sends is checked
1140
+ * and spent like any other, because a token that is ignored when it is wrong is decoration.
1141
+ */
1142
+ token?: string;
1143
+ }): Promise<SubmissionOutcome>;
1144
+ //#endregion
986
1145
  //#region src/redos.d.ts
987
1146
  /**
988
1147
  * Refuse a form whose `pattern` values can be made to backtrack.
@@ -1221,7 +1380,189 @@ export declare function publishForm(deps: ServerDeps, input: {
1221
1380
  * asks to be told it has been overtaken.
1222
1381
  */
1223
1382
  basedOnSchemaHash?: string;
1383
+ /** The request this publish is answering, which its audit row names (`AuditEntry.requestId`). */
1384
+ requestId?: string;
1224
1385
  }): Promise<PublishOutcome>;
1225
1386
  //#endregion
1226
- export { type Action, type Actor, type AttemptOutcome, type AuditAction, type AuditDraft, type AuditEntry, type AuthDeps, type AuthOutcome, type BreakerState, CHALLENGE_TTL_SECONDS, type Challenge, type ClaimOutcome, DEFAULT_MAX_NUMBER, type DeliveryHeaders, type DeliveryRecord, type DraftMigration, type DraftRecord, type FileRecord, type FormRecord, type FormVersionRecord, type ListedForm, type ListedSubmission, type ListedVersion, type MembershipOutcome, type OfferDeps, type OfferInput, type OfferOutcome, type OutboxDeps, type PublishOutcome, type ReplayOutcome, type ResolvedForm, type ResumeOutcome, type Role, type ScanVerdict, type Scanner, type ScreenOutcome, type ServerDeps, type ServerOptionsSource, type ServerOptionsSources, type Solution, type Storage, type SubmissionOutcome, type SubmissionRecord, type UnsafePattern, type VerifyOutcome, type WebhookHealth, type WebhookRecord, decodeSolution, encodeSolution, hashOf, mintChallenge, solveChallenge, verifySolution };
1387
+ //#region src/examples.d.ts
1388
+ /**
1389
+ * A form's examples, kept by the deployment beside the form, and run when it is published
1390
+ * ([0166](../../../docs/decisions/0166-a-deployment-keeps-a-forms-examples-and-runs-them-at-publish.md)).
1391
+ *
1392
+ * An example with its answer written down is the one check that tells a condition that
1393
+ * compiles from the condition that was asked for
1394
+ * ([0110](../../../docs/decisions/0110-a-form-is-checked-against-examples.md)). The builders
1395
+ * run them, and the scenarios are the host's to keep
1396
+ * ([0111](../../../docs/decisions/0111-a-scenario-panel-names-what-stopped-holding.md)); on a
1397
+ * deployment the host is this server, so it keeps them, with the fictional sample they start
1398
+ * from, and publishing — the last moment before a version is frozen — runs them.
1399
+ *
1400
+ * **The permission is decided here, not in the route.** Reading and changing a form's
1401
+ * examples take what editing the form takes, `form.publish`, and a host composing its own
1402
+ * HTTP over this package gets that rule with the use-case rather than having to remember it.
1403
+ *
1404
+ * **What is kept is read as what is sent is read**, by `readList`, on the way in and on the
1405
+ * way out. A list sent to be kept with anything in it that is not an example keeps nothing; a
1406
+ * row already kept that is not one — edited around `keepExamples` — is left out and named
1407
+ * wherever the examples are read back, so the admin that draws them and the publish that runs
1408
+ * them are only ever handed examples.
1409
+ */
1410
+ /** A form's examples as a builder holds them: the list, and where every one starts. */
1411
+ interface FormExamples {
1412
+ readonly scenarios: readonly Scenario[];
1413
+ /** Absent when none was kept: every example then starts from an empty form. */
1414
+ readonly sample?: Readonly<Record<string, unknown>>;
1415
+ /**
1416
+ * When they are read back: what is kept and is not an example, or not a sample, one sentence
1417
+ * each. Left out of the above, so nothing draws or runs it, and gone at the next save, which
1418
+ * keeps only what it is sent. Absent when everything kept could be read.
1419
+ */
1420
+ readonly unreadable?: readonly string[];
1421
+ }
1422
+ type ExamplesOutcome = {
1423
+ readonly ok: true;
1424
+ readonly examples: FormExamples;
1425
+ } |
1426
+ /** Not with this actor's role: a viewer may read the form, and not what it is checked against. */
1427
+ {
1428
+ readonly ok: false;
1429
+ readonly kind: 'forbidden';
1430
+ } |
1431
+ /** Examples are kept beside a form, so there must be one at this path. */
1432
+ {
1433
+ readonly ok: false;
1434
+ readonly kind: 'unknown_form';
1435
+ };
1436
+ type KeepExamplesOutcome = ExamplesOutcome |
1437
+ /** Something sent is not an example, or not a sample: one sentence each, and nothing kept. */
1438
+ {
1439
+ readonly ok: false;
1440
+ readonly kind: 'invalid_examples';
1441
+ readonly problems: readonly string[];
1442
+ };
1443
+ /** The examples kept for the form at `path`; none, for a form nobody wrote any for. */
1444
+ export declare function readExamples(deps: ServerDeps, input: {
1445
+ path: string;
1446
+ actor: Actor;
1447
+ }): Promise<ExamplesOutcome>;
1448
+ /**
1449
+ * Replace the examples of the form at `path`, and the sample they start from.
1450
+ *
1451
+ * Each is read as an example the way a builder reads a model's draft — `readScenario`, one
1452
+ * decision for both — and a list with any item that is not one keeps nothing. Paths are not
1453
+ * checked against the published form: an example is written for the form being edited, which
1454
+ * may name a field no version has yet, and the runner says so when it runs.
1455
+ */
1456
+ export declare function keepExamples(deps: ServerDeps,
1457
+ /** `requestId` is the request this change answers, which its audit row names. */
1458
+ input: {
1459
+ path: string;
1460
+ actor: Actor;
1461
+ examples: unknown;
1462
+ requestId?: string;
1463
+ }): Promise<KeepExamplesOutcome>;
1464
+ //#endregion
1465
+ //#region src/model.d.ts
1466
+ /**
1467
+ * The deployment's own model, asked on a builder's behalf.
1468
+ *
1469
+ * The builders ask a model through an `AskModel` the host supplies, and a key in a browser
1470
+ * is a key anybody who opens the page can read. So a deployment that has a model keeps it
1471
+ * here, behind its own sessions, and the admin's `AskModel` is a request to this server
1472
+ * ([0165](../../../docs/decisions/0165-a-deployments-model-is-asked-through-its-server.md)).
1473
+ *
1474
+ * **The server writes the briefing.** The browser names the kind of request — one of the
1475
+ * three formancy makes — and sends the user part; the system part is the one
1476
+ * `@formancy/builder-core` briefs that kind with, and one in the request is never read, so
1477
+ * every request the operator's key pays for is asked under one of formancy's briefings.
1478
+ * That narrows the endpoint; it does not close it. The user part is still the person's
1479
+ * text, and nothing here stops it asking the model for something else under formancy's
1480
+ * briefing: the permission, the rate limit, the size cap and the output limit bound what
1481
+ * that costs, and the audit log says who asked.
1482
+ */
1483
+ /** Everything a completion is asked: one system part and one user part, no conversation. */
1484
+ interface CompletionPrompt {
1485
+ readonly system: string;
1486
+ readonly user: string;
1487
+ }
1488
+ /**
1489
+ * Told when whoever asked has gone, so the request is abandoned at the provider rather than
1490
+ * paid for to the end.
1491
+ *
1492
+ * A callback rather than an `AbortSignal`, which this package's types do not have
1493
+ * ([0008](../../../docs/decisions/0008-layered-packages.md)) — the shape builder-core's
1494
+ * `AskTurn` has for the same reason. An adapter wires it in one line:
1495
+ * `const c = new AbortController(); cancellation.onCancel(() => c.abort())`.
1496
+ */
1497
+ interface Cancellation {
1498
+ /** Called at most once: when the asker goes, or at once if it already has. */
1499
+ onCancel(listener: () => void): void;
1500
+ }
1501
+ /**
1502
+ * What one completion came to. Only the first is an answer.
1503
+ *
1504
+ * - `refused`: the provider declined in its response rather than in its text. `reason` is
1505
+ * for the person, and ends their run as a decline
1506
+ * ([0158](../../../docs/decisions/0158-a-model-may-decline.md)).
1507
+ * - `truncated`: the answer reached the output limit. Cut off, it is not an answer, and
1508
+ * is never handed over as half a document.
1509
+ * - `unavailable`: not reached, or it answered with an error. `status` is the provider's
1510
+ * HTTP status when it gave one; `cause` is for the operator's log, never the client.
1511
+ * - `cancelled`: the asker went away and the request was abandoned.
1512
+ */
1513
+ type Completion = {
1514
+ readonly ok: true;
1515
+ readonly text: string;
1516
+ } | {
1517
+ readonly ok: false;
1518
+ readonly failure: 'refused';
1519
+ readonly reason: string;
1520
+ } | {
1521
+ readonly ok: false;
1522
+ readonly failure: 'truncated';
1523
+ } | {
1524
+ readonly ok: false;
1525
+ readonly failure: 'unavailable';
1526
+ readonly status?: number;
1527
+ readonly cause: string;
1528
+ } | {
1529
+ readonly ok: false;
1530
+ readonly failure: 'cancelled';
1531
+ };
1532
+ /**
1533
+ * A model, asked to complete one prompt.
1534
+ *
1535
+ * A port because what is behind it is genuinely swappable: the deployment chooses Anthropic,
1536
+ * OpenAI or xAI, `@formancy/server` has an adapter for each, and the tests drive the route
1537
+ * through doubles. **It does not throw for a provider's failure**; it says which failure.
1538
+ */
1539
+ interface Completer {
1540
+ complete(prompt: CompletionPrompt, cancellation: Cancellation): Promise<Completion>;
1541
+ }
1542
+ /** A builder's request as the browser sends it, unread. */
1543
+ interface BuilderRequest {
1544
+ readonly kind?: unknown;
1545
+ readonly user?: unknown;
1546
+ }
1547
+ type BuilderRequestOutcome = Completion |
1548
+ /** Not one of the requests formancy makes, so there is no briefing to ask it under. */
1549
+ {
1550
+ readonly ok: false;
1551
+ readonly failure: 'unknown_kind';
1552
+ } |
1553
+ /** No text to ask about: the briefing alone, which no run sends. */
1554
+ {
1555
+ readonly ok: false;
1556
+ readonly failure: 'no_user';
1557
+ };
1558
+ /**
1559
+ * Ask the deployment's model a builder's request, under the briefing for its kind.
1560
+ *
1561
+ * Whatever else the request carries is not read — a `system` above all. Resolves on every
1562
+ * ending: an adapter that throws broke its contract, and is still a model that could not
1563
+ * be asked.
1564
+ */
1565
+ export declare function completeBuilderRequest(completer: Completer, request: BuilderRequest, cancellation: Cancellation): Promise<BuilderRequestOutcome>;
1566
+ //#endregion
1567
+ export { type Action, type Actor, type AttemptOutcome, type AuditAction, type AuditDraft, type AuditEntry, type AuthDeps, type AuthOutcome, type BreakerState, type BuilderRequest, type BuilderRequestOutcome, CHALLENGE_TTL_SECONDS, type Cancellation, type Challenge, type ClaimOutcome, type Completer, type Completion, type CompletionPrompt, DEFAULT_MAX_NUMBER, type DeliveryHeaders, type DeliveryRecord, type DraftMigration, type DraftRecord, type ExamplesOutcome, type ExamplesRecord, type FileRecord, type FormExamples, type FormRecord, type FormToFill, type FormVersionRecord, type KeepExamplesOutcome, type ListedForm, type ListedSubmission, type ListedVersion, type MembershipOutcome, type OfferDeps, type OfferInput, type OfferOutcome, type OutboxDeps, type PublishOutcome, type ReplayOutcome, type ResolvedForm, type ResumeOutcome, type Role, type ScanVerdict, type Scanner, type ScreenOutcome, type ServerDeps, type ServerOptionsSource, type ServerOptionsSources, type Solution, type Storage, type SubmissionOutcome, type SubmissionRecord, type UnsafePattern, type VerifyOutcome, type WebhookHealth, type WebhookRecord, decodeSolution, encodeSolution, hashOf, mintChallenge, solveChallenge, verifySolution };
1227
1568
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/options-membership.ts","../src/ports.ts","../src/auth.ts","../src/audit.ts","../src/outbox.ts","../src/breaker.ts","../src/uploads.ts","../src/deps.ts","../src/use-cases.ts","../src/redos.ts","../src/testing/memory-storage.ts","../src/address.ts","../src/webhook.ts","../src/publishing.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;UAoBiB;;;;;;;;;;;;EAYf,SAAS,4BAA4B;;KAG3B,uBAAuB,SAAS,eAAe;;;;;;;;;wBAU3C,eACd,QAAQ,YACR,iBACC;EAAgB;EAAc;EAAgB;;;KAiDrC;EACN;;;;EAEA;EAAW;EAAiB,QAAQ;;;;;;;;;;EAQpC;EAAW;EAA4B;;;;;;;;wBAQvB,gBACpB,QAAQ,YACR,gBACA,SAAS,mCACR,QAAQ;;;;;;wBA8CK,cAAc,QAAQ;;;;;;;;UC7JrB;EACf;EACA;EACA;;;;;;;;;;EAUA;;;;;;EAMA;;UAGe;EACf;EACA;EACA;EACA,QAAQ;EACR;;UAGe;EACf;EACA;EACA;EACA;EACA;;UAGe;EACf;EACA;EACA;EACA,MAAM;EACN;;UAGe;EACf;EACA;;EAEA;EACA;EACA,MAAM;EACN;EACA;;UAGe;EACf;EACA;EACA;EACA;EACA;;;UAIe;EACf;EACA;EACA;;EAEA;;;;;;;;;EASA;;EAEA;;;;;;;;;;;UAYe;EACf;EACA;EACA;;EAEA;EACA;EACA;;EAEA;;EAEA;EACA;;;;;;;;;;;;;;;;;;UAmBe;EACf;EACA;;EAEA;EACA;EACA;;EAEA;EACA;EACA;;EAEA;;UAGe;EACf,cAAc,eAAe,QAAQ;EACrC,aAAa,QAAQ;EACrB,WAAW,QAAQ,aAAa;EAChC,iBACE,gBACA,QAAQ,KAAK,iDACZ;EACH,kBAAkB,gBAAgB,oBAAoB;EACtD,cAAc,QAAQ,oBAAoB;;;;;;;;;;;;;;;;;;;EAoB1C,eAAe;IACb,OAAO;IACP,SAAS;IACT,QAAQ;MACN;EACJ,eAAe,aAAa,QAAQ;EACpC,kBAAkB,gBAAgB,qBAAqB,QAAQ;EAC/D,oBAAoB,iBAAiB;;;;;;;;;;;;;;;;;EAiBrC,iBACE,QAAQ,kBACR,sBAAsB,kBACtB,kCACA,QAAQ,aACP;;;;;;;;;;;;;;EAeH,YAAY,OAAO,aAAa;;EAGhC,UAAU,gBAAgB,QAAQ;;;;;;;;;;;;;;;EAgBlC,eAAe,mBAAmB,uBAAuB;;EAGzD,wBAAwB,oBAAoB;EAE5C,WAAW,QAAQ,aAAa;EAChC,QAAQ,aAAa,QAAQ;EAC7B,WAAW,QAAQ,aAAa;;EAEhC,eAAe,oBAAoB,QAAQ;EAC3C,YAAY,yBAAyB;EACrC,gBAAgB,iBAAiB,QAAQ;EACzC,cAAc,QAAQ,gBAAgB;;EAEtC,cAAc,QAAQ,gBAAgB;EACtC,gBAAgB,QAAQ;;;;;;;;EAQxB,eAAe,gBAAgB,QAAQ;EACvC,YAAY,aAAa,QAAQ;;EAEjC,mBAAmB,gBAAgB,gBAAgB,QAAQ;EAC3D,eAAe,QAAQ,iBAAiB;EACxC,mBAAmB,QAAQ;;EAE3B,sBAAsB,iBAAiB,QAAQ;EAC/C,mBAAmB,iBAAiB,QAAQ;EAC5C,YAAY,QAAQ,cAAc;EAClC,SAAS,gBAAgB,kBAAkB,QAAQ;EACnD,WAAW,QAAQ,aAAa;EAChC,eAAe,gBAAgB,QAAQ;EACvC,aAAa,QAAQ,eAAe;EACpC,eAAe,QAAQ;EACvB,oBAAoB,iBAAiB,QAAQ;EAC7C,aAAa,YAAY,gBAAgB;;;;;;;;;;;;KC9Q/B;UAEK;EACf;EACA;EACA,MAAM;;UAGS;EACf,SAAS;EACT;EACA;;EAEA;EACA,WAAW,iBAAiB;EAC5B,aAAa,gBAAgB,eAAe;;KAKlC;EACN;EAAU;;EACV;EAAW;;wBAEK,gBACpB,MAAM,UACN;EAAS;EAAe;EAAkB,MAAM;IAC/C,QAAQ;KAmBC;EAAgB;EAAU,OAAO;;EAAY;;;;;;;wBAOnC,kBACpB,MAAM,UACN;EAAS;EAAe;IACvB,QAAQ;KAYC;EACN;EAAU;EAAY;;EACtB;EAAW;;wBAEK,aACpB,MAAM,UACN;EAAS;EAAc,MAAM;IAC5B,QAAQ;wBAmBW,mBAAmB,MAAM,UAAU,oBAAoB,QAAQ;;;;;;;;KAkBzE;wBAwBI,IAAI,OAAO,OAAO,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;qBCzH7B;KAiBD,sBAAsB;UAEjB;WACN;WACA;WACA,QAAQ;;;;;WAKR;WACA;;;;;;WAMA;;;;;WAKA;;WAEA,SAAS,SAAS;;;KAIjB,aAAa,KAAK;;;;;;;;wBASd,UAAU,OAAO,mBAAmB,OAAO,KAAK,uCAAuC;;;;;;;;;;UCnEtF;EACf;EACA;EACA;;wBAGc,aACd,UAAU,gBACV,SAAS,gBACT,KAAK,MACL,uBACC;UAyBc;EACf,SAAS;;EAET,OACE,UAAU,gBACV,SAAS,eACT,uBACG,QAAQ;EACb,WAAW;EACX;;;;;;;;;;;;;;;wBAgBoB,YAAY,MAAM,YAAY,iBAAa;;;;;;;;;;;;;;;;;;;KAqFrD;EACN;EAAU,UAAU;;EACpB;EAAW;EAA8B,QAAQ;;wBAEjC,eACpB;EAAQ,SAAS;EAAS,WAAW;GACrC,aACC,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;qBC1IE;;;;;;;;;qBAUA;;KAGD;wBAEI,aAAa,SAAS,eAAe,KAAK,OAAO;;wBAYjD,WAAW,SAAS,eAAe,KAAK;;;;;;;;wBAWxC,oBACd,SAAS,eACT,aACA,KAAK,OACJ;;;;;;;;UAuBc;EACf;EACA;EACA,OAAO;EACP;;EAEA;;wBAGc,SAAS,SAAS,eAAe,KAAK,OAAO;;;;;;;;;;;;;;;;;;;;;;UC5E5C;EACf,SAAS;EACT,WAAW;EACX;;UAGe;EACf,QAAQ;;EAER,MAAM;EACN;EACA;;EAEA;EACA;EACA;EACA;;KAGU;EACN;EAAU,MAAM;;EAEhB;EACA;;;;;;;;;;wBAWgB,YAAY,MAAM,WAAW,OAAO,aAAa,QAAQ;;KAsCnE;EAAgB;;EAAkB;EAAc;;;;;;;;;UAS3C;EACf,KACE;IAAQ;IAAc;IAAqB;KAC3C,OAAO,aACN,QAAQ;;KAGD;EACN;;EACA;EAAW;EAAmB;;;;EAE9B;EAAW;EAA+B;;;;;;;;;;;;wBAY1B,aACpB,SAAS,qBACT;EAAQ;EAAc;EAAqB;GAC3C,OAAO,aACN,QAAQ;KAkBC;EACN;EAAU;;EACV;EAAW;;;;;;;;;;;;;;;;;;;;wBAoBK,aACpB,SAAS,SACT;EAAS,QAAQ;EAAY;EAAgB;IAC5C,QAAQ;;;;;;;;;wBA6BW,sBACpB,SAAS,SACT,KAAK,MACL,qBACC,QAAQ;;wBAkGK,eAAe,QAAQ;;;;;;;;;;;UCtStB;EACf,SAAS;EACT;EACA;;;;;;;;;EASA,SAAS,eAAe;;EAExB,cAAc;;;;;;;;;;EAUd;;;;;;;;;;;;;;;EAeA,iBAAiB;;;;;EAKjB,UAAU;;;;;;;;;;;UCtCK;EACf;EACA;EACA;EACA,QAAQ;EACR;;wBAGoB,YAAY,MAAM,YAAY,eAAe,QAAQ;KAc/D;EACN;EAAU;EAAY;;EACtB;EAAW;;EACX;EAAW;EAAyB,UAAU;;EAC9C;EAAW;EAAiB,QAAQ;;;;EAEpC;EAAW;;;;;;;;;;EAQX;EAAW;EAA4B;;;;;;;;;;;;;;;;;;wBAkBvB,cACpB,MAAM,YACN;EAAS;EAAc;EAAoC;IAC1D;EAAU;;wBAYS,iBACpB,MAAM,YACN;EACE;EACA;EACA;;EAEA;EACA;IAED,QAAQ;UA4HM;EACf;EACA;EACA;EACA;;;;;wBAMoB,gBACpB,MAAM,YACN,eACC,QAAQ;;;;;;;;;;;wBA0BW,UAAU,MAAM,YAAY,eAAe;;;;;;;;wBA4G3C,WACpB,MAAM,YACN;EAAS;IACR;EAAU;EAAiB;;wBAQR,UACpB,MAAM,YACN;EAAS;EAAc;EAAiB;EAAe;IACtD;EAAU;EAAiB;;UAqBb;EACf;EACA,SAAS;;KAGC;EAEN;EACA;EACA,QAAQ;EACR;EACA;;EAEA,YAAY;;;;EAKZ;EACA;EACA,QAAQ;EACR;;;;;;;;;;;;;;wBAegB,YACpB,MAAM,YACN;EAAS;EAAc;EAAiB;IACvC,QAAQ;UAkIM;EACf;EACA;EACA;EACA;;;wBAIoB,UAAU,MAAM,aAAa,QAAQ;UAiB1C;EACf;EACA;EACA;;;;wBAKoB,aACpB,MAAM,YACN,eACC,QAAQ;;;;;;;;;;;;;;;;;;;UCtkBM;;EAEf;EACA;;EAEA;;;;;;;;;;;wBAqCoB,eAAe,QAAQ,aAAa,QAAQ;;;;;;;;wBC3DlD,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;wBCgCvB,iBAAiB;;;;;;;;;wBAkDjB,YAAY;;;;;;;;;;;qBC/Ef;qBACA;UAEI;GACd;;;;;;;;;;wBAWa,cAAc,0BAA0B;;wBAKxC,SAAS,gBAAgB,0BAA0B;;;;;;;;wBAWnD,gBAAgB;EAC9B;EACA;EACA;EACA;EACA;IACE;;;;;;;wBAiBY,gBAAgB;EAC9B;EACA;EACA;EACA;EACA;;;;;;;;;;wBA4Cc,aAAa,iBAAiB;;qBAQjC;;;;;;;;;;KCvGD;EAEN;EACA;EACA;EACA;EACA;;;;;;;;;;EAUA;;EAEA;EAAW;EAAwB,SAAS;;EAC5C;EAAW;EAAuB;;EAClC;EAAW;EAAwB,UAAU;;;;EAE7C;EAAW;EAAgC;;;;;;;;;EAO3C;EAAW;EAAyB,UAAU;;;;;;;;;;;;;;EAY9C;EAAW;EAA2B;;;;;;;;;;;wBAWtB,YACpB,MAAM,YACN;EACE;EACA;EACA,QAAQ;;;;;;;;;;;EAWR;IAED,QAAQ"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/options-membership.ts","../src/ports.ts","../src/auth.ts","../src/audit.ts","../src/outbox.ts","../src/breaker.ts","../src/uploads.ts","../src/deps.ts","../src/use-cases.ts","../src/submitting.ts","../src/redos.ts","../src/testing/memory-storage.ts","../src/address.ts","../src/webhook.ts","../src/publishing.ts","../src/examples.ts","../src/model.ts"],"mappings":"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"}