@decionis/agent-safe-pipeline 0.3.7 → 0.4.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 (85) hide show
  1. package/README.md +31 -0
  2. package/dist/Index.d.ts +12 -0
  3. package/dist/Index.d.ts.map +1 -1
  4. package/dist/Index.js +12 -0
  5. package/dist/Index.js.map +1 -1
  6. package/dist/decision/DecionisGate.d.ts +6 -1
  7. package/dist/decision/DecionisGate.d.ts.map +1 -1
  8. package/dist/decision/DecionisGate.js +61 -11
  9. package/dist/decision/DecionisGate.js.map +1 -1
  10. package/dist/decision/DecisionAuthority.d.ts +16 -0
  11. package/dist/decision/DecisionAuthority.d.ts.map +1 -1
  12. package/dist/decision/DecisionAuthority.js.map +1 -1
  13. package/dist/execution/AuthorizationVerifier.d.ts +33 -4
  14. package/dist/execution/AuthorizationVerifier.d.ts.map +1 -1
  15. package/dist/execution/AuthorizationVerifier.js +74 -10
  16. package/dist/execution/AuthorizationVerifier.js.map +1 -1
  17. package/dist/execution/EffectAdapter.d.ts +117 -0
  18. package/dist/execution/EffectAdapter.d.ts.map +1 -0
  19. package/dist/execution/EffectAdapter.js +22 -0
  20. package/dist/execution/EffectAdapter.js.map +1 -0
  21. package/dist/execution/ExecutionDeadline.d.ts +35 -0
  22. package/dist/execution/ExecutionDeadline.d.ts.map +1 -0
  23. package/dist/execution/ExecutionDeadline.js +52 -0
  24. package/dist/execution/ExecutionDeadline.js.map +1 -0
  25. package/dist/execution/ExecutionJournal.d.ts +148 -0
  26. package/dist/execution/ExecutionJournal.d.ts.map +1 -0
  27. package/dist/execution/ExecutionJournal.js +157 -0
  28. package/dist/execution/ExecutionJournal.js.map +1 -0
  29. package/dist/execution/ExecutionOutcome.d.ts +186 -0
  30. package/dist/execution/ExecutionOutcome.d.ts.map +1 -0
  31. package/dist/execution/ExecutionOutcome.js +2 -0
  32. package/dist/execution/ExecutionOutcome.js.map +1 -0
  33. package/dist/execution/ExecutionPosture.d.ts +50 -0
  34. package/dist/execution/ExecutionPosture.d.ts.map +1 -0
  35. package/dist/execution/ExecutionPosture.js +20 -0
  36. package/dist/execution/ExecutionPosture.js.map +1 -0
  37. package/dist/execution/ExecutorEvidence.d.ts +64 -0
  38. package/dist/execution/ExecutorEvidence.d.ts.map +1 -0
  39. package/dist/execution/ExecutorEvidence.js +14 -0
  40. package/dist/execution/ExecutorEvidence.js.map +1 -0
  41. package/dist/execution/GovernedExecutionRunner.d.ts +309 -0
  42. package/dist/execution/GovernedExecutionRunner.d.ts.map +1 -0
  43. package/dist/execution/GovernedExecutionRunner.js +1341 -0
  44. package/dist/execution/GovernedExecutionRunner.js.map +1 -0
  45. package/dist/execution/NativeExecutor.d.ts +220 -0
  46. package/dist/execution/NativeExecutor.d.ts.map +1 -0
  47. package/dist/execution/NativeExecutor.js +22 -0
  48. package/dist/execution/NativeExecutor.js.map +1 -0
  49. package/dist/execution/NativeExecutorSchema.d.ts +387 -0
  50. package/dist/execution/NativeExecutorSchema.d.ts.map +1 -0
  51. package/dist/execution/NativeExecutorSchema.js +261 -0
  52. package/dist/execution/NativeExecutorSchema.js.map +1 -0
  53. package/dist/execution/PostgresExecutionJournal.d.ts +54 -0
  54. package/dist/execution/PostgresExecutionJournal.d.ts.map +1 -0
  55. package/dist/execution/PostgresExecutionJournal.js +131 -0
  56. package/dist/execution/PostgresExecutionJournal.js.map +1 -0
  57. package/dist/execution/RegistryExecutor.d.ts +35 -0
  58. package/dist/execution/RegistryExecutor.d.ts.map +1 -0
  59. package/dist/execution/RegistryExecutor.js +84 -0
  60. package/dist/execution/RegistryExecutor.js.map +1 -0
  61. package/dist/execution/SafeExecutor.d.ts +22 -193
  62. package/dist/execution/SafeExecutor.d.ts.map +1 -1
  63. package/dist/execution/SafeExecutor.js +49 -521
  64. package/dist/execution/SafeExecutor.js.map +1 -1
  65. package/dist/http/AuthorityPaths.d.ts +51 -0
  66. package/dist/http/AuthorityPaths.d.ts.map +1 -0
  67. package/dist/http/AuthorityPaths.js +84 -0
  68. package/dist/http/AuthorityPaths.js.map +1 -0
  69. package/dist/shadow/ShadowPipeline.d.ts +3 -1
  70. package/dist/shadow/ShadowPipeline.d.ts.map +1 -1
  71. package/dist/shadow/ShadowPipeline.js +3 -3
  72. package/dist/shadow/ShadowPipeline.js.map +1 -1
  73. package/dist/testing/Index.d.ts +2 -1
  74. package/dist/testing/Index.d.ts.map +1 -1
  75. package/dist/testing/Index.js +2 -1
  76. package/dist/testing/Index.js.map +1 -1
  77. package/dist/testing/LocalAuthority.d.ts +35 -1
  78. package/dist/testing/LocalAuthority.d.ts.map +1 -1
  79. package/dist/testing/LocalAuthority.js +122 -2
  80. package/dist/testing/LocalAuthority.js.map +1 -1
  81. package/dist/testing/SignedSignals.d.ts +150 -0
  82. package/dist/testing/SignedSignals.d.ts.map +1 -0
  83. package/dist/testing/SignedSignals.js +291 -0
  84. package/dist/testing/SignedSignals.js.map +1 -0
  85. package/package.json +1 -1
@@ -0,0 +1,54 @@
1
+ import { type DispatchedAuthorization, type ExecutionJournal, type JournalRecord, type OpenAttempt } from "./ExecutionJournal.js";
2
+ import type { SqlClient } from "./PostgresReplayStore.js";
3
+ export interface PostgresExecutionJournalOptions {
4
+ readonly client: SqlClient;
5
+ /**
6
+ * Whose attempts these are: the organisation the executor runs for. Two
7
+ * deployments that share a database never read each other's records, and
8
+ * an idempotency key is single-use within one namespace.
9
+ */
10
+ readonly namespace: string;
11
+ /** The journal table, optionally schema-qualified; `agentsafe_execution_journal` by default. */
12
+ readonly table?: string;
13
+ }
14
+ export declare const DEFAULT_JOURNAL_TABLE = "agentsafe_execution_journal";
15
+ /**
16
+ * The execution journal every replica shares: one row per record, appended
17
+ * and never updated, read back in insertion order and folded with the same
18
+ * functions the file journal uses, so the two cannot disagree about which
19
+ * attempts are open or what an intent was dispatched under.
20
+ *
21
+ * It is the durable form of what `journaledActionHandler` does in the
22
+ * runtime: the `GRANT_CLAIMED` record is written after the grant is consumed
23
+ * and before the provider is touched, and a write that fails throws, so the
24
+ * runner reports a failure before dispatch rather than an effect nobody
25
+ * journaled. Single use of an idempotency key is the database's decision: a
26
+ * partial unique index on `(namespace, idempotency_key)` over claim records
27
+ * refuses the second claim, so two replicas racing on one key dispatch once,
28
+ * and the loser is told `IDEMPOTENCY_KEY_DISPATCHED`.
29
+ *
30
+ * The operator creates the table (`PostgresExecutionJournal.schema()`); the
31
+ * executor's role needs SELECT and INSERT on it and nothing else. Rows hold
32
+ * the captured intent, parameters included, so the table is as sensitive as
33
+ * the requests themselves.
34
+ */
35
+ export declare class PostgresExecutionJournal implements ExecutionJournal {
36
+ private readonly client;
37
+ private readonly namespace;
38
+ private readonly table;
39
+ constructor(options: PostgresExecutionJournalOptions);
40
+ /** The DDL an operator runs once, before the first replica starts. */
41
+ static schema(table?: string): string;
42
+ append(record: JournalRecord): Promise<void>;
43
+ openAttempts(): Promise<readonly OpenAttempt[]>;
44
+ authorizationsOf(intentId: string): Promise<readonly DispatchedAuthorization[]>;
45
+ dispatchedUnder(idempotencyKey: string): Promise<readonly DispatchedAuthorization[]>;
46
+ /** Throws unless the table exists with the columns this journal uses. */
47
+ probe(): Promise<void>;
48
+ /** The client belongs to the caller, who opened it and closes it. */
49
+ close(): void;
50
+ /** The rows' records that parse, in order; a row that does not is skipped, as a bad file line is. */
51
+ private read;
52
+ private static json;
53
+ }
54
+ //# sourceMappingURL=PostgresExecutionJournal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PostgresExecutionJournal.d.ts","sourceRoot":"","sources":["../../src/execution/PostgresExecutionJournal.ts"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,uBAAuB,EAC5B,KAAK,gBAAgB,EACrB,KAAK,aAAa,EAClB,KAAK,WAAW,EACjB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAE1D,MAAM,WAAW,+BAA+B;IAC9C,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B;;;;OAIG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,gGAAgG;IAChG,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,eAAO,MAAM,qBAAqB,gCAAgC,CAAC;AAOnE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,wBAAyB,YAAW,gBAAgB;IAC/D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAY;IACnC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;gBAEZ,OAAO,EAAE,+BAA+B;IAW3D,sEAAsE;WACxD,MAAM,CAAC,KAAK,SAAwB,GAAG,MAAM;IAmB9C,MAAM,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAoB5C,YAAY,IAAI,OAAO,CAAC,SAAS,WAAW,EAAE,CAAC;IAc/C,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,uBAAuB,EAAE,CAAC;IAQ/E,eAAe,CAC1B,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,SAAS,uBAAuB,EAAE,CAAC;IAU9C,yEAAyE;IAC5D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAOnC,qEAAqE;IAC9D,KAAK,IAAI,IAAI;IAEpB,qGAAqG;YACvF,IAAI;IAelB,OAAO,CAAC,MAAM,CAAC,IAAI;CAQpB"}
@@ -0,0 +1,131 @@
1
+ import { authorizationsFrom, dispatchedUnderFrom, IDEMPOTENCY_KEY_DISPATCHED, JournalError, JournalRecordSchema, openAttemptsFrom, } from "./ExecutionJournal.js";
2
+ export const DEFAULT_JOURNAL_TABLE = "agentsafe_execution_journal";
3
+ /** A lowercase SQL identifier, or `schema.table`: interpolated into SQL, so nothing else is. */
4
+ const TABLE = /^[a-z_][a-z0-9_]{0,62}(?:\.[a-z_][a-z0-9_]{0,62})?$/;
5
+ /** The SQLSTATE a unique index answers a second insert with. */
6
+ const UNIQUE_VIOLATION = "23505";
7
+ /**
8
+ * The execution journal every replica shares: one row per record, appended
9
+ * and never updated, read back in insertion order and folded with the same
10
+ * functions the file journal uses, so the two cannot disagree about which
11
+ * attempts are open or what an intent was dispatched under.
12
+ *
13
+ * It is the durable form of what `journaledActionHandler` does in the
14
+ * runtime: the `GRANT_CLAIMED` record is written after the grant is consumed
15
+ * and before the provider is touched, and a write that fails throws, so the
16
+ * runner reports a failure before dispatch rather than an effect nobody
17
+ * journaled. Single use of an idempotency key is the database's decision: a
18
+ * partial unique index on `(namespace, idempotency_key)` over claim records
19
+ * refuses the second claim, so two replicas racing on one key dispatch once,
20
+ * and the loser is told `IDEMPOTENCY_KEY_DISPATCHED`.
21
+ *
22
+ * The operator creates the table (`PostgresExecutionJournal.schema()`); the
23
+ * executor's role needs SELECT and INSERT on it and nothing else. Rows hold
24
+ * the captured intent, parameters included, so the table is as sensitive as
25
+ * the requests themselves.
26
+ */
27
+ export class PostgresExecutionJournal {
28
+ client;
29
+ namespace;
30
+ table;
31
+ constructor(options) {
32
+ const table = options.table ?? DEFAULT_JOURNAL_TABLE;
33
+ if (!TABLE.test(table))
34
+ throw new Error("JOURNAL_TABLE_INVALID");
35
+ if (options.namespace.length === 0 || options.namespace.length > 200) {
36
+ throw new Error("JOURNAL_NAMESPACE_INVALID");
37
+ }
38
+ this.client = options.client;
39
+ this.namespace = options.namespace;
40
+ this.table = table;
41
+ }
42
+ /** The DDL an operator runs once, before the first replica starts. */
43
+ static schema(table = DEFAULT_JOURNAL_TABLE) {
44
+ if (!TABLE.test(table))
45
+ throw new Error("JOURNAL_TABLE_INVALID");
46
+ const index = table.replace(".", "_");
47
+ return [
48
+ `CREATE TABLE IF NOT EXISTS ${table} (`,
49
+ " seq bigserial PRIMARY KEY,",
50
+ " namespace text NOT NULL,",
51
+ " intent_id text NOT NULL,",
52
+ " record_kind text NOT NULL,",
53
+ " idempotency_key text,",
54
+ " record jsonb NOT NULL,",
55
+ " recorded_at timestamptz NOT NULL DEFAULT now()",
56
+ ");",
57
+ `CREATE INDEX IF NOT EXISTS ${index}_intent ON ${table} (namespace, intent_id, seq);`,
58
+ `CREATE UNIQUE INDEX IF NOT EXISTS ${index}_claim_once ON ${table} (namespace, idempotency_key) WHERE record_kind = 'GRANT_CLAIMED';`,
59
+ "",
60
+ ].join("\n");
61
+ }
62
+ async append(record) {
63
+ const parsed = JournalRecordSchema.safeParse(record);
64
+ if (!parsed.success)
65
+ throw new JournalError("JOURNAL_RECORD_INVALID");
66
+ const value = parsed.data;
67
+ // Only a claim carries the key into its indexed column: the unique index
68
+ // is over claims, and an opening record with the same key is not a use.
69
+ const key = value.record === "GRANT_CLAIMED" ? value.idempotency_key : null;
70
+ try {
71
+ await this.client.query(`INSERT INTO ${this.table} (namespace, intent_id, record_kind, idempotency_key, record) VALUES ($1, $2, $3, $4, $5)`, [this.namespace, value.intent_id, value.record, key, JSON.stringify(value)]);
72
+ }
73
+ catch (error) {
74
+ if (error?.code === UNIQUE_VIOLATION) {
75
+ throw new JournalError(IDEMPOTENCY_KEY_DISPATCHED);
76
+ }
77
+ throw new JournalError("JOURNAL_WRITE_FAILED");
78
+ }
79
+ }
80
+ async openAttempts() {
81
+ // An attempt is open until its intent has a closing record. Intent ids
82
+ // are fresh per capture and opened once, so excluding every intent that
83
+ // has one is exactly the fold's answer, without reading closed history.
84
+ const rows = await this.read(`SELECT record FROM ${this.table} WHERE namespace = $1 AND intent_id IN (` +
85
+ `SELECT intent_id FROM ${this.table} WHERE namespace = $1 AND record_kind = 'ATTEMPT_OPENED' ` +
86
+ `EXCEPT SELECT intent_id FROM ${this.table} WHERE namespace = $1 AND record_kind IN ('ATTEMPT_CLOSED', 'RECONCILED')` +
87
+ `) ORDER BY seq`, [this.namespace]);
88
+ return openAttemptsFrom(rows);
89
+ }
90
+ async authorizationsOf(intentId) {
91
+ const rows = await this.read(`SELECT record FROM ${this.table} WHERE namespace = $1 AND intent_id = $2 ORDER BY seq`, [this.namespace, intentId]);
92
+ return authorizationsFrom(rows, intentId);
93
+ }
94
+ async dispatchedUnder(idempotencyKey) {
95
+ const rows = await this.read(`SELECT record FROM ${this.table} WHERE namespace = $1 AND intent_id IN (` +
96
+ `SELECT intent_id FROM ${this.table} WHERE namespace = $1 AND record_kind = 'GRANT_CLAIMED' AND idempotency_key = $2` +
97
+ `) ORDER BY seq`, [this.namespace, idempotencyKey]);
98
+ return dispatchedUnderFrom(rows, idempotencyKey);
99
+ }
100
+ /** Throws unless the table exists with the columns this journal uses. */
101
+ async probe() {
102
+ await this.client.query(`SELECT seq, namespace, intent_id, record_kind, idempotency_key, record FROM ${this.table} LIMIT 0`, []);
103
+ }
104
+ /** The client belongs to the caller, who opened it and closes it. */
105
+ close() { }
106
+ /** The rows' records that parse, in order; a row that does not is skipped, as a bad file line is. */
107
+ async read(text, values) {
108
+ const result = await this.client.query(text, values);
109
+ // Stryker disable next-line ArrayDeclaration: a seed element is not a record, and every fold ignores what is not one.
110
+ const records = [];
111
+ // Stryker disable next-line ArrayDeclaration: an element of the fallback is not a row with a record, and is skipped.
112
+ for (const row of result.rows ?? []) {
113
+ const raw = row.record;
114
+ const value = typeof raw === "string" ? PostgresExecutionJournal.json(raw) : raw;
115
+ const parsed = JournalRecordSchema.safeParse(value);
116
+ if (parsed.success)
117
+ records.push(parsed.data);
118
+ }
119
+ return records;
120
+ }
121
+ // Stryker disable all: an unparsable row is skipped either way, read as null or as undefined.
122
+ static json(text) {
123
+ try {
124
+ return JSON.parse(text);
125
+ }
126
+ catch {
127
+ return null;
128
+ }
129
+ }
130
+ }
131
+ //# sourceMappingURL=PostgresExecutionJournal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PostgresExecutionJournal.js","sourceRoot":"","sources":["../../src/execution/PostgresExecutionJournal.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,0BAA0B,EAC1B,YAAY,EACZ,mBAAmB,EACnB,gBAAgB,GAKjB,MAAM,uBAAuB,CAAC;AAe/B,MAAM,CAAC,MAAM,qBAAqB,GAAG,6BAA6B,CAAC;AAEnE,gGAAgG;AAChG,MAAM,KAAK,GAAG,qDAAqD,CAAC;AACpE,gEAAgE;AAChE,MAAM,gBAAgB,GAAG,OAAO,CAAC;AAEjC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,OAAO,wBAAwB;IAClB,MAAM,CAAY;IAClB,SAAS,CAAS;IAClB,KAAK,CAAS;IAE/B,YAAmB,OAAwC;QACzD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,qBAAqB,CAAC;QACrD,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;QACjE,IAAI,OAAO,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,CAAC,SAAS,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;YACrE,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;QAC/C,CAAC;QACD,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;QAC7B,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;QACnC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;IAED,sEAAsE;IAC/D,MAAM,CAAC,MAAM,CAAC,KAAK,GAAG,qBAAqB;QAChD,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;QACjE,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QACtC,OAAO;YACL,8BAA8B,KAAK,IAAI;YACvC,8BAA8B;YAC9B,4BAA4B;YAC5B,4BAA4B;YAC5B,8BAA8B;YAC9B,yBAAyB;YACzB,0BAA0B;YAC1B,kDAAkD;YAClD,IAAI;YACJ,8BAA8B,KAAK,cAAc,KAAK,+BAA+B;YACrF,qCAAqC,KAAK,kBAAkB,KAAK,oEAAoE;YACrI,EAAE;SACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACf,CAAC;IAEM,KAAK,CAAC,MAAM,CAAC,MAAqB;QACvC,MAAM,MAAM,GAAG,mBAAmB,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QACrD,IAAI,CAAC,MAAM,CAAC,OAAO;YAAE,MAAM,IAAI,YAAY,CAAC,wBAAwB,CAAC,CAAC;QACtE,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC;QAC1B,yEAAyE;QACzE,wEAAwE;QACxE,MAAM,GAAG,GAAG,KAAK,CAAC,MAAM,KAAK,eAAe,CAAC,CAAC,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC;QAC5E,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CACrB,eAAe,IAAI,CAAC,KAAK,2FAA2F,EACpH,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAC5E,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAK,KAA4C,EAAE,IAAI,KAAK,gBAAgB,EAAE,CAAC;gBAC7E,MAAM,IAAI,YAAY,CAAC,0BAA0B,CAAC,CAAC;YACrD,CAAC;YACD,MAAM,IAAI,YAAY,CAAC,sBAAsB,CAAC,CAAC;QACjD,CAAC;IACH,CAAC;IAEM,KAAK,CAAC,YAAY;QACvB,uEAAuE;QACvE,wEAAwE;QACxE,wEAAwE;QACxE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,CAC1B,sBAAsB,IAAI,CAAC,KAAK,0CAA0C;YACxE,yBAAyB,IAAI,CAAC,KAAK,2DAA2D;YAC9F,gCAAgC,IAAI,CAAC,KAAK,2EAA2E;YACrH,gBAAgB,EAClB,CAAC,IAAI,CAAC,SAAS,CAAC,CACjB,CAAC;QACF,OAAO,gBAAgB,CAAC,IAAI,CAAC,CAAC;IAChC,CAAC;IAEM,KAAK,CAAC,gBAAgB,CAAC,QAAgB;QAC5C,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,CAC1B,sBAAsB,IAAI,CAAC,KAAK,uDAAuD,EACvF,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAC3B,CAAC;QACF,OAAO,kBAAkB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC5C,CAAC;IAEM,KAAK,CAAC,eAAe,CAC1B,cAAsB;QAEtB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,CAC1B,sBAAsB,IAAI,CAAC,KAAK,0CAA0C;YACxE,yBAAyB,IAAI,CAAC,KAAK,kFAAkF;YACrH,gBAAgB,EAClB,CAAC,IAAI,CAAC,SAAS,EAAE,cAAc,CAAC,CACjC,CAAC;QACF,OAAO,mBAAmB,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;IACnD,CAAC;IAED,yEAAyE;IAClE,KAAK,CAAC,KAAK;QAChB,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CACrB,+EAA+E,IAAI,CAAC,KAAK,UAAU,EACnG,EAAE,CACH,CAAC;IACJ,CAAC;IAED,qEAAqE;IAC9D,KAAK,KAAU,CAAC;IAEvB,qGAAqG;IAC7F,KAAK,CAAC,IAAI,CAAC,IAAY,EAAE,MAA0B;QACzD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACrD,sHAAsH;QACtH,MAAM,OAAO,GAAoB,EAAE,CAAC;QACpC,qHAAqH;QACrH,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;YACpC,MAAM,GAAG,GAAI,GAAqC,CAAC,MAAM,CAAC;YAC1D,MAAM,KAAK,GAAY,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,wBAAwB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;YAC1F,MAAM,MAAM,GAAG,mBAAmB,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;YACpD,IAAI,MAAM,CAAC,OAAO;gBAAE,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAChD,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,8FAA8F;IACtF,MAAM,CAAC,IAAI,CAAC,IAAY;QAC9B,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAY,CAAC;QACrC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;CAEF"}
@@ -0,0 +1,35 @@
1
+ import type { CapturedIntent } from "../intent/ExecutionIntent.js";
2
+ import type { ActionExecutionAttempt, ActionRegistry } from "./ActionRegistry.js";
3
+ import type { ClaimedExecution, EffectObservation, ExecutionCapability, ExecutionEffect, NativeExecutor, PreparedAction, ReconcileContext, ReconcileResult } from "./NativeExecutor.js";
4
+ /**
5
+ * The dispatch-style executor an `ActionRegistry` already is: every
6
+ * registered handler, run by intent, behind the contract. It is how
7
+ * `SafeExecutor` and the runtime's registry reach `GovernedExecutionRunner`
8
+ * without a change to a single handler: the registry keeps its dispatch
9
+ * tracking, its refusals and its single-flight reconciliation, and this
10
+ * class only reads what it reports into the contract's terms.
11
+ *
12
+ * The action it executes is the captured intent itself, so what it prepares
13
+ * is exactly what was decided: there is no second description of the action
14
+ * that could drift from the one the authority bound.
15
+ */
16
+ export declare class RegistryExecutor implements NativeExecutor<CapturedIntent, ActionExecutionAttempt, unknown> {
17
+ private readonly registry;
18
+ readonly platform: string;
19
+ readonly version = "registry/1";
20
+ readonly style: "dispatch";
21
+ readonly actionTypes: readonly string[];
22
+ constructor(registry: ActionRegistry, platform?: string);
23
+ /** The registry knows its handlers, not a connection; it states no capability to check. */
24
+ capabilities(): Promise<readonly ExecutionCapability[]>;
25
+ /**
26
+ * Refuses an unregistered action or parameters its handler's schema does
27
+ * not accept, by throwing exactly as the registry's own validation does.
28
+ */
29
+ prepare(captured: CapturedIntent): Promise<PreparedAction>;
30
+ /** The registry tracks its own dispatch boundary; what it reports is carried through verbatim. */
31
+ execute(run: ClaimedExecution<CapturedIntent>): Promise<ExecutionEffect<ActionExecutionAttempt>>;
32
+ observe(effect: ExecutionEffect<ActionExecutionAttempt>): Promise<EffectObservation<unknown>>;
33
+ reconcile(context: ReconcileContext): Promise<ReconcileResult<unknown>>;
34
+ }
35
+ //# sourceMappingURL=RegistryExecutor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RegistryExecutor.d.ts","sourceRoot":"","sources":["../../src/execution/RegistryExecutor.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAEnE,OAAO,KAAK,EAAE,sBAAsB,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAClF,OAAO,KAAK,EACV,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,eAAe,EACf,cAAc,EACd,cAAc,EACd,gBAAgB,EAChB,eAAe,EAChB,MAAM,qBAAqB,CAAC;AAG7B;;;;;;;;;;;GAWG;AACH,qBAAa,gBAAiB,YAAW,cAAc,CACrD,cAAc,EACd,sBAAsB,EACtB,OAAO,CACR;IAOG,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAN3B,SAAgB,QAAQ,EAAE,MAAM,CAAC;IACjC,SAAgB,OAAO,gBAAgB;IACvC,SAAgB,KAAK,EAAG,UAAU,CAAU;IAC5C,SAAgB,WAAW,EAAE,SAAS,MAAM,EAAE,CAAM;gBAGjC,QAAQ,EAAE,cAAc,EACzC,QAAQ,SAAoB;IAK9B,2FAA2F;IAC9E,YAAY,IAAI,OAAO,CAAC,SAAS,mBAAmB,EAAE,CAAC;IAIpE;;;OAGG;IACU,OAAO,CAAC,QAAQ,EAAE,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC;IAkBvE,kGAAkG;IACrF,OAAO,CAClB,GAAG,EAAE,gBAAgB,CAAC,cAAc,CAAC,GACpC,OAAO,CAAC,eAAe,CAAC,sBAAsB,CAAC,CAAC;IAQtC,OAAO,CAClB,MAAM,EAAE,eAAe,CAAC,sBAAsB,CAAC,GAC9C,OAAO,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAwBzB,SAAS,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;CAGrF"}
@@ -0,0 +1,84 @@
1
+ import { CanonicalIntentHasher } from "../intent/CanonicalIntentHasher.js";
2
+ import { createHash } from "node:crypto";
3
+ /**
4
+ * The dispatch-style executor an `ActionRegistry` already is: every
5
+ * registered handler, run by intent, behind the contract. It is how
6
+ * `SafeExecutor` and the runtime's registry reach `GovernedExecutionRunner`
7
+ * without a change to a single handler: the registry keeps its dispatch
8
+ * tracking, its refusals and its single-flight reconciliation, and this
9
+ * class only reads what it reports into the contract's terms.
10
+ *
11
+ * The action it executes is the captured intent itself, so what it prepares
12
+ * is exactly what was decided: there is no second description of the action
13
+ * that could drift from the one the authority bound.
14
+ */
15
+ export class RegistryExecutor {
16
+ registry;
17
+ platform;
18
+ version = "registry/1";
19
+ style = "dispatch";
20
+ actionTypes = [];
21
+ constructor(registry, platform = "action-registry") {
22
+ this.registry = registry;
23
+ this.platform = platform;
24
+ }
25
+ /** The registry knows its handlers, not a connection; it states no capability to check. */
26
+ async capabilities() {
27
+ return await Promise.resolve([]);
28
+ }
29
+ /**
30
+ * Refuses an unregistered action or parameters its handler's schema does
31
+ * not accept, by throwing exactly as the registry's own validation does.
32
+ */
33
+ async prepare(captured) {
34
+ this.registry.validate(captured);
35
+ const intent = captured.intent;
36
+ const canonical = CanonicalIntentHasher.stringify(intent.parameters);
37
+ return await Promise.resolve({
38
+ actionType: intent.action,
39
+ proposal: { action: intent.action, target: intent.target, parameters: intent.parameters },
40
+ downstreamTarget: intent.downstreamTarget,
41
+ idempotencyKey: intent.idempotencyKey,
42
+ expectedEffectDigest: intent.expectedEffectDigest === undefined
43
+ ? null
44
+ : intent.expectedEffectDigest,
45
+ requestDigest: `sha256:${createHash("sha256").update(canonical).digest("hex")}`,
46
+ facts: {},
47
+ });
48
+ }
49
+ /** The registry tracks its own dispatch boundary; what it reports is carried through verbatim. */
50
+ async execute(run) {
51
+ const attempt = await this.registry.executeTracked(run.action, run.authorization);
52
+ if (attempt.status === "FAILED_BEFORE_DISPATCH") {
53
+ return { kind: "NOT_DISPATCHED", code: attempt.code };
54
+ }
55
+ return { kind: "DISPATCHED", receipt: attempt, signedReceipt: attempt.receipt };
56
+ }
57
+ async observe(effect) {
58
+ const attempt = effect.kind === "DISPATCHED" ? effect.receipt : null;
59
+ if (attempt === null || attempt.status === "FAILED_BEFORE_DISPATCH") {
60
+ return await Promise.resolve({ status: "INDETERMINATE", reason: null, result: null });
61
+ }
62
+ if (attempt.status === "COMPLETED") {
63
+ return {
64
+ status: "COMMITTED",
65
+ reason: null,
66
+ result: attempt.result,
67
+ signedReceipt: attempt.receipt,
68
+ };
69
+ }
70
+ if (attempt.status === "REFUSED_AFTER_DISPATCH") {
71
+ return {
72
+ status: "FAILED",
73
+ reason: attempt.reason,
74
+ result: null,
75
+ signedReceipt: attempt.receipt,
76
+ };
77
+ }
78
+ return { status: "INDETERMINATE", reason: null, result: null, signedReceipt: attempt.receipt };
79
+ }
80
+ async reconcile(context) {
81
+ return await this.registry.reconcile(context.intent, context.idempotencyKey);
82
+ }
83
+ }
84
+ //# sourceMappingURL=RegistryExecutor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RegistryExecutor.js","sourceRoot":"","sources":["../../src/execution/RegistryExecutor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAc3E,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC;;;;;;;;;;;GAWG;AACH,MAAM,OAAO,gBAAgB;IAWR;IANH,QAAQ,CAAS;IACjB,OAAO,GAAG,YAAY,CAAC;IACvB,KAAK,GAAG,UAAmB,CAAC;IAC5B,WAAW,GAAsB,EAAE,CAAC;IAEpD,YACmB,QAAwB,EACzC,QAAQ,GAAG,iBAAiB;QADX,aAAQ,GAAR,QAAQ,CAAgB;QAGzC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED,2FAA2F;IACpF,KAAK,CAAC,YAAY;QACvB,OAAO,MAAM,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACnC,CAAC;IAED;;;OAGG;IACI,KAAK,CAAC,OAAO,CAAC,QAAwB;QAC3C,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACjC,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC;QAC/B,MAAM,SAAS,GAAG,qBAAqB,CAAC,SAAS,CAAC,MAAM,CAAC,UAAuB,CAAC,CAAC;QAClF,OAAO,MAAM,OAAO,CAAC,OAAO,CAAC;YAC3B,UAAU,EAAE,MAAM,CAAC,MAAM;YACzB,QAAQ,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE;YACzF,gBAAgB,EAAE,MAAM,CAAC,gBAAgB;YACzC,cAAc,EAAE,MAAM,CAAC,cAAc;YACrC,oBAAoB,EAClB,MAAM,CAAC,oBAAoB,KAAK,SAAS;gBACvC,CAAC,CAAC,IAAI;gBACN,CAAC,CAAE,MAAM,CAAC,oBAA2C;YACzD,aAAa,EAAE,UAAU,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;YAC/E,KAAK,EAAE,EAAE;SACV,CAAC,CAAC;IACL,CAAC;IAED,kGAAkG;IAC3F,KAAK,CAAC,OAAO,CAClB,GAAqC;QAErC,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,aAAa,CAAC,CAAC;QAClF,IAAI,OAAO,CAAC,MAAM,KAAK,wBAAwB,EAAE,CAAC;YAChD,OAAO,EAAE,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC;QACxD,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC;IAClF,CAAC;IAEM,KAAK,CAAC,OAAO,CAClB,MAA+C;QAE/C,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,KAAK,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;QACrE,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,CAAC,MAAM,KAAK,wBAAwB,EAAE,CAAC;YACpE,OAAO,MAAM,OAAO,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QACxF,CAAC;QACD,IAAI,OAAO,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;YACnC,OAAO;gBACL,MAAM,EAAE,WAAW;gBACnB,MAAM,EAAE,IAAI;gBACZ,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,aAAa,EAAE,OAAO,CAAC,OAAO;aAC/B,CAAC;QACJ,CAAC;QACD,IAAI,OAAO,CAAC,MAAM,KAAK,wBAAwB,EAAE,CAAC;YAChD,OAAO;gBACL,MAAM,EAAE,QAAQ;gBAChB,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,MAAM,EAAE,IAAI;gBACZ,aAAa,EAAE,OAAO,CAAC,OAAO;aAC/B,CAAC;QACJ,CAAC;QACD,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC;IACjG,CAAC;IAEM,KAAK,CAAC,SAAS,CAAC,OAAyB;QAC9C,OAAO,MAAM,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IAC/E,CAAC;CACF"}
@@ -4,7 +4,8 @@ import type { CapturedIntent } from "../intent/ExecutionIntent.js";
4
4
  import type { JsonObject } from "../intent/JsonValue.js";
5
5
  import type { ActionRegistry } from "./ActionRegistry.js";
6
6
  import type { AuthorizationVerifier, ExecutionCommitOutcome, ExecutionFinalization, VerifiedAuthorization } from "./AuthorizationVerifier.js";
7
- export type ExecutionBlockReason = "DECISION_NOT_AUTHORITATIVE" | "DECISION_NOT_ALLOW" | "INTENT_BINDING_MISMATCH" | "INTENT_CONFORMANCE_FAILED" | "AUTHORIZATION_MISSING" | "AUTHORIZATION_INVALID" | "RECOVERY_BINDING_MISMATCH" | "RECOVERY_ATTEMPT_UNKNOWN" | "BOUNDARY_MISMATCH" | "WORKLOAD_MISMATCH" | "AUDIT_UNAVAILABLE";
7
+ import type { DispatchedAttempts, ExecutionBlockedResult, ExecutionHeldResult, ExecutionReconciliationResult, ExecutionRecoveryReference, HeldClaimResult, HeldExecution, SafeExecutionResult } from "./ExecutionOutcome.js";
8
+ export type { DispatchedAttempts, ExecutionBlockedResult, ExecutionBlockReason, ExecutionHeldResult, ExecutionPreDispatchFailureReason, ExecutionReconciliationResult, ExecutionRecoveryReference, HeldClaimResult, HeldExecution, ProviderOutcomeUnknownResult, ProviderRefusedResult, SafeExecutionResult, } from "./ExecutionOutcome.js";
8
9
  /**
9
10
  * What this executor is, beyond the registry and the verifier it was given.
10
11
  *
@@ -35,155 +36,24 @@ export interface SafeExecutorOptions {
35
36
  */
36
37
  readonly attempts?: DispatchedAttempts;
37
38
  }
38
- /** Where an executor reads back the authorizations it dispatched an intent under. */
39
- export interface DispatchedAttempts {
40
- /** Every authorization journaled for this intent, oldest first; none when it was never dispatched here. */
41
- authorizationsOf(captured: CapturedIntent): Promise<readonly VerifiedAuthorization[]>;
42
- }
43
- export type ExecutionPreDispatchFailureReason = "HANDLER_FAILED_BEFORE_DISPATCH" | "AUDIT_UNAVAILABLE";
44
39
  /**
45
- * What a caller presents back to reconcile an attempt whose outcome was
46
- * lost. The fields are listed rather than inherited, because this is a
47
- * versioned wire object: a field that appears on `VerifiedAuthorization`
48
- * later must be added here deliberately or not at all.
49
- */
50
- export interface ExecutionRecoveryReference {
51
- readonly version: "agent-safe.recovery/1";
52
- readonly decisionId: string;
53
- readonly dossierId: string;
54
- readonly grantId: string;
55
- readonly intentHash: string;
56
- readonly expiresAt: string;
57
- readonly idempotencyKey: string;
58
- }
59
- export interface ExecutionBlockedResult {
60
- readonly outcome: "BLOCKED";
61
- readonly executed: false;
62
- readonly reason: ExecutionBlockReason;
63
- readonly result: null;
64
- readonly authorization: null;
65
- }
66
- /**
67
- * The provider refused, definitively, after the dispatch boundary. The grant
68
- * was consumed and the request was sent, and nothing was effected: the
69
- * outcome is a fact, not an unknown, so there is nothing to reconcile and no
70
- * recovery reference to present. A caller that wants the action after all
71
- * needs a fresh decision and a fresh grant, because the refusal was about
72
- * this attempt.
73
- */
74
- export interface ProviderRefusedResult {
75
- readonly outcome: "DEFINITELY_NOT_EXECUTED";
76
- readonly executed: false;
77
- readonly recovered: false;
78
- /** The provider's own reason, as the handler reported it. */
79
- readonly reason: string;
80
- readonly result: null;
81
- readonly authorization: VerifiedAuthorization;
82
- }
83
- export interface ProviderOutcomeUnknownResult {
84
- readonly outcome: "UNKNOWN_AFTER_DISPATCH";
85
- readonly executed: null;
86
- readonly reason: "PROVIDER_OUTCOME_UNKNOWN";
87
- readonly result: null;
88
- readonly authorization: VerifiedAuthorization;
89
- readonly recovery: ExecutionRecoveryReference;
90
- }
91
- /**
92
- * Every outcome that consumed a grant reports whether the attempt's commit
93
- * evidence reached the authority. Finalization is evidence, not authority;
94
- * it never changes `outcome` or `executed`.
95
- */
96
- export type SafeExecutionResult<TResult = unknown> = {
97
- readonly outcome: "COMPLETED";
98
- readonly executed: true;
99
- readonly recovered: false;
100
- readonly result: TResult;
101
- readonly authorization: VerifiedAuthorization;
102
- readonly finalization: ExecutionFinalization;
103
- } | ExecutionBlockedResult | {
104
- readonly outcome: "FAILED_BEFORE_DISPATCH";
105
- readonly executed: false;
106
- readonly reason: ExecutionPreDispatchFailureReason;
107
- /** Why the handler refused, when it threw a `PreDispatchRefusal`. */
108
- readonly code?: string;
109
- readonly result: null;
110
- readonly authorization: VerifiedAuthorization;
111
- readonly finalization: ExecutionFinalization;
112
- } | (ProviderRefusedResult & {
113
- readonly finalization: ExecutionFinalization;
114
- }) | (ProviderOutcomeUnknownResult & {
115
- readonly finalization: ExecutionFinalization;
116
- });
117
- export type ExecutionReconciliationResult<TResult = unknown> = {
118
- readonly outcome: "COMPLETED";
119
- readonly executed: true;
120
- readonly recovered: true;
121
- readonly result: TResult;
122
- readonly authorization: VerifiedAuthorization;
123
- } | {
124
- readonly outcome: "DEFINITELY_NOT_EXECUTED";
125
- readonly executed: false;
126
- readonly recovered: true;
127
- readonly reason: "PROVIDER_CONFIRMED_NOT_EXECUTED";
128
- readonly result: null;
129
- readonly authorization: VerifiedAuthorization;
130
- } | ExecutionBlockedResult | ProviderOutcomeUnknownResult;
131
- /**
132
- * A grant admitted for a later claim. Every check `run` makes before it
133
- * consumes a grant has passed, and nothing has been consumed: the grant is
134
- * still the authority's to hand out once. Only `hold` issues one, only the
135
- * executor that issued it can claim it, and it is claimed at most once.
40
+ * The registry-shaped face of `GovernedExecutionRunner`, kept so that every
41
+ * caller written against it keeps its signatures and its outcomes exactly.
42
+ * Each method is the runner's, with the registry as the executor: admission,
43
+ * the claim, finalization, holds and reconciliation all happen in the
44
+ * runner, and nothing here decides anything.
136
45
  *
137
- * This is for an effect that another system performs at a moment this
138
- * process does not choose, such as a card authorization the issuer asks
139
- * about in milliseconds: the decision is made before, the grant waits here,
140
- * and the claim happens when that system asks for it.
46
+ * Two runner behaviours stay off behind this face, because they did not
47
+ * exist when it was written: the runner does not refuse a dispatch whose
48
+ * window closed (the registry's handlers bound their own dispatch), and it
49
+ * does not report reconciliations to the authority. Code that wants either
50
+ * uses the runner, with a `NativeExecutor`, directly.
141
51
  */
142
- export interface HeldExecution {
143
- readonly captured: CapturedIntent;
144
- readonly decision: DecisionGate;
145
- /** The grant's own expiry: after it there is nothing left to claim. */
146
- readonly expiresAt: string;
147
- }
148
- export interface ExecutionHeldResult {
149
- readonly outcome: "HELD";
150
- readonly executed: false;
151
- readonly result: null;
152
- readonly authorization: null;
153
- readonly held: HeldExecution;
154
- }
155
- export type HeldClaimResult = {
156
- readonly outcome: "CLAIMED";
157
- readonly authorization: VerifiedAuthorization;
158
- } | ExecutionBlockedResult | Extract<SafeExecutionResult<never>, {
159
- outcome: "FAILED_BEFORE_DISPATCH";
160
- }>;
161
52
  export declare class SafeExecutor {
162
- private readonly registry;
163
- private readonly verifier;
164
- private readonly audit?;
165
- private readonly hasher;
166
- private readonly boundaryId;
167
- private readonly workloadDigest;
168
- /** The holds this executor issued and nobody has claimed, keyed by the frozen handle. */
169
- private readonly holds;
170
- /** The holds claimed and not yet settled, with the authorization each one consumed. */
171
- private readonly claims;
172
- private readonly attempts;
173
- constructor(registry: ActionRegistry, verifier: AuthorizationVerifier, audit?: AuditRecorder | undefined, options?: SafeExecutorOptions);
53
+ private readonly runner;
54
+ private readonly executor;
55
+ constructor(registry: ActionRegistry, verifier: AuthorizationVerifier, audit?: AuditRecorder, options?: SafeExecutorOptions);
174
56
  run<TResult = unknown>(captured: CapturedIntent, decision: DecisionGate): Promise<SafeExecutionResult<TResult>>;
175
- /**
176
- * Every check made before a grant may be consumed, with the evidence that
177
- * the intent was captured and decided. A refusal is recorded and returned;
178
- * null means the decision passed, and so carries a grant.
179
- */
180
- private admit;
181
- /**
182
- * Consumes the grant through the verifier, checks what came back against
183
- * the decision and the intent, and records the consumption and the start
184
- * of execution. Nothing here dispatches.
185
- */
186
- private consume;
187
57
  /**
188
58
  * Admits a decision exactly as `run` would and holds its grant instead of
189
59
  * consuming it. The intent, the decision and the hold are recorded; the
@@ -195,18 +65,14 @@ export declare class SafeExecutor {
195
65
  * Admits a hold this executor did not make: one another replica made, or
196
66
  * this process made before a restart, read back from a store the replicas
197
67
  * share. Every check `hold` makes is made again on the way in, and the
198
- * record says the hold was adopted. Adoption adds no authority: the grant
199
- * is still the authority's to hand out once, so a hold claimed elsewhere
200
- * is refused at the claim by the authority or the shared replay store,
201
- * never admitted twice by this executor's own memory.
68
+ * record says the hold was adopted.
202
69
  */
203
70
  adoptHold(captured: CapturedIntent, decision: DecisionGate): Promise<ExecutionHeldResult | ExecutionBlockedResult>;
204
71
  /**
205
72
  * Registers a claim this executor did not make, so that `settleHeld` can
206
- * finalize it here: the hold's intent and decision, and the authorization
207
- * the claim returned, as the store that shared them kept them. Nothing is
208
- * consumed and nothing is checked against the authority; the finalization
209
- * is, as always, the authority's to accept or refuse.
73
+ * finalize it here. Nothing is consumed and nothing is checked against the
74
+ * authority; the finalization is, as always, the authority's to accept or
75
+ * refuse.
210
76
  */
211
77
  adoptClaim(captured: CapturedIntent, decision: DecisionGate, authorization: VerifiedAuthorization, material?: JsonObject | null): HeldExecution;
212
78
  /**
@@ -215,13 +81,10 @@ export declare class SafeExecutor {
215
81
  * verifier keeps its claims to itself or did not make this one.
216
82
  */
217
83
  claimMaterial(authorization: VerifiedAuthorization): JsonObject | null;
218
- private holdWith;
219
84
  /**
220
- * Claims a held grant, once. The handle is forgotten before the verifier
221
- * is asked, so a second claim of the same hold, concurrent or later, is
222
- * refused here without reaching the authority; a handle this executor did
223
- * not issue is refused the same way. What the claim returns is checked
224
- * exactly as `run` checks it.
85
+ * Claims a held grant, once. A second claim of the same hold, concurrent or
86
+ * later, is refused without reaching the authority; a handle this executor
87
+ * did not issue is refused the same way.
225
88
  */
226
89
  claimHeld(held: HeldExecution): Promise<HeldClaimResult>;
227
90
  /**
@@ -230,40 +93,6 @@ export declare class SafeExecutor {
230
93
  * nobody can say. The terminal record names the outcome, as `run`'s do.
231
94
  */
232
95
  settleHeld(held: HeldExecution, outcome: ExecutionCommitOutcome, receipt?: string | null): Promise<ExecutionFinalization>;
233
- private static settledEvent;
234
- /**
235
- * Reports the attempt outcome to the verifier's authority, with the
236
- * provider's effect receipt when the attempt brought one back. A missing,
237
- * failing, or malformed finalization can never alter the execution result.
238
- */
239
- private finalize;
240
- private static finalizationCode;
241
96
  reconcile<TResult = unknown>(captured: CapturedIntent, recovery: ExecutionRecoveryReference): Promise<ExecutionReconciliationResult<TResult>>;
242
- /**
243
- * Observational artifacts carry an explicit non-authoritative marker. They
244
- * must never be interpreted as a `DecisionGate`, even after an unsafe cast
245
- * or a JSON round trip.
246
- */
247
- private static isAuthoritativeDecision;
248
- /**
249
- * Whether this boundary is the one the intent was captured through. The
250
- * boundary is read back out of the hashed context, so an intent whose
251
- * boundary was edited after capture fails conformance before it reaches
252
- * here, and one that never named a boundary cannot acquire one now.
253
- */
254
- private boundaryMatches;
255
- /**
256
- * Whether the workload that proposed the intent is the one running it. Like
257
- * the boundary, the digest is read back out of the hashed context, so an
258
- * intent whose workload was edited after capture fails conformance first.
259
- */
260
- private workloadMatches;
261
- private intentConforms;
262
- private block;
263
- private failedBeforeDispatch;
264
- private record;
265
- private static recoveryReference;
266
- private static sameBinding;
267
- private static authorizationFrom;
268
97
  }
269
98
  //# sourceMappingURL=SafeExecutor.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"SafeExecutor.d.ts","sourceRoot":"","sources":["../../src/execution/SafeExecutor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SafeExecutor.d.ts","sourceRoot":"","sources":["../../src/execution/SafeExecutor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EACV,qBAAqB,EACrB,sBAAsB,EACtB,qBAAqB,EACrB,qBAAqB,EACtB,MAAM,4BAA4B,CAAC;AACpC,OAAO,KAAK,EACV,kBAAkB,EAClB,sBAAsB,EACtB,mBAAmB,EACnB,6BAA6B,EAC7B,0BAA0B,EAC1B,eAAe,EACf,aAAa,EACb,mBAAmB,EACpB,MAAM,uBAAuB,CAAC;AAI/B,YAAY,EACV,kBAAkB,EAClB,sBAAsB,EACtB,oBAAoB,EACpB,mBAAmB,EACnB,iCAAiC,EACjC,6BAA6B,EAC7B,0BAA0B,EAC1B,eAAe,EACf,aAAa,EACb,4BAA4B,EAC5B,qBAAqB,EACrB,mBAAmB,GACpB,MAAM,uBAAuB,CAAC;AAE/B;;;;;;;;;GASG;AACH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B;;;;;;OAMG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC;;;;;;;OAOG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,kBAAkB,CAAC;CACxC;AAED;;;;;;;;;;;;GAYG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA0B;IACjD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAmB;gBAG1C,QAAQ,EAAE,cAAc,EACxB,QAAQ,EAAE,qBAAqB,EAC/B,KAAK,CAAC,EAAE,aAAa,EACrB,OAAO,CAAC,EAAE,mBAAmB;IAclB,GAAG,CAAC,OAAO,GAAG,OAAO,EAChC,QAAQ,EAAE,cAAc,EACxB,QAAQ,EAAE,YAAY,GACrB,OAAO,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC;IAQxC;;;;;OAKG;IACU,IAAI,CACf,QAAQ,EAAE,cAAc,EACxB,QAAQ,EAAE,YAAY,GACrB,OAAO,CAAC,mBAAmB,GAAG,sBAAsB,CAAC;IAIxD;;;;;OAKG;IACU,SAAS,CACpB,QAAQ,EAAE,cAAc,EACxB,QAAQ,EAAE,YAAY,GACrB,OAAO,CAAC,mBAAmB,GAAG,sBAAsB,CAAC;IAIxD;;;;;OAKG;IACI,UAAU,CACf,QAAQ,EAAE,cAAc,EACxB,QAAQ,EAAE,YAAY,EACtB,aAAa,EAAE,qBAAqB,EACpC,QAAQ,GAAE,UAAU,GAAG,IAAW,GACjC,aAAa;IAShB;;;;OAIG;IACI,aAAa,CAAC,aAAa,EAAE,qBAAqB,GAAG,UAAU,GAAG,IAAI;IAI7E;;;;OAIG;IACU,SAAS,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,eAAe,CAAC;IAIrE;;;;OAIG;IACU,UAAU,CACrB,IAAI,EAAE,aAAa,EACnB,OAAO,EAAE,sBAAsB,EAC/B,OAAO,GAAE,MAAM,GAAG,IAAW,GAC5B,OAAO,CAAC,qBAAqB,CAAC;IAMpB,SAAS,CAAC,OAAO,GAAG,OAAO,EACtC,QAAQ,EAAE,cAAc,EACxB,QAAQ,EAAE,0BAA0B,GACnC,OAAO,CAAC,6BAA6B,CAAC,OAAO,CAAC,CAAC;CAOnD"}