@prestack/thread 0.1.2 → 0.1.4

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 (265) hide show
  1. package/CHANGELOG.md +193 -0
  2. package/dist/core/actor.d.ts +1 -1
  3. package/dist/core/actor.js +5 -4
  4. package/dist/core/actor.ts +5 -4
  5. package/dist/core/attach.d.ts +0 -7
  6. package/dist/core/attach.js +67 -58
  7. package/dist/core/attach.ts +61 -68
  8. package/dist/core/chain.js +13 -17
  9. package/dist/core/chain.ts +11 -15
  10. package/dist/core/condition.d.ts +4 -4
  11. package/dist/core/condition.js +2 -2
  12. package/dist/core/descend.d.ts +4 -2
  13. package/dist/core/descend.js +89 -21
  14. package/dist/core/descend.ts +86 -17
  15. package/dist/core/errors/catalogue.d.ts +52 -0
  16. package/dist/{operations/errors/errors.js → core/errors/catalogue.js} +1 -1
  17. package/dist/{operations/errors/errors.ts → core/errors/catalogue.ts} +1 -1
  18. package/dist/{operations/errors/catalog.d.ts → core/errors/error.d.ts} +2 -3
  19. package/dist/{operations/errors/catalog.js → core/errors/error.js} +1 -16
  20. package/dist/{operations/errors/catalog.ts → core/errors/error.ts} +3 -19
  21. package/dist/core/errors/namespaces.d.ts +3 -0
  22. package/dist/core/errors/namespaces.js +15 -0
  23. package/dist/core/errors/namespaces.ts +19 -0
  24. package/dist/core/finding.js +2 -2
  25. package/dist/core/finding.ts +1 -2
  26. package/dist/core/init.d.ts +0 -2
  27. package/dist/core/init.js +51 -15
  28. package/dist/core/init.ts +58 -15
  29. package/dist/core/invoked.d.ts +1 -1
  30. package/dist/core/invoked.js +3 -1
  31. package/dist/core/invoked.ts +5 -2
  32. package/dist/core/round.js +36 -22
  33. package/dist/core/round.ts +26 -9
  34. package/dist/core/rows.d.ts +4 -0
  35. package/dist/core/rows.js +31 -2
  36. package/dist/core/rows.ts +33 -1
  37. package/dist/core/thread.d.ts +3 -3
  38. package/dist/core/tree.d.ts +4 -1
  39. package/dist/core/tree.js +26 -6
  40. package/dist/core/tree.ts +29 -6
  41. package/dist/core/types.d.ts +3 -3
  42. package/dist/core/types.js +3 -1
  43. package/dist/core/types.ts +2 -1
  44. package/dist/derivation/attach.js +1 -1
  45. package/dist/derivation/generators/build.js +6 -6
  46. package/dist/derivation/generators/build.ts +1 -1
  47. package/dist/derivation/generators/check.js +1 -1
  48. package/dist/derivation/generators/determinism.js +1 -1
  49. package/dist/derivation/generators/release.js +60 -47
  50. package/dist/derivation/generators/release.ts +66 -43
  51. package/dist/derivation/release.d.ts +7 -3
  52. package/dist/derivation/release.js +14 -1
  53. package/dist/derivation/release.ts +22 -2
  54. package/dist/integrations/attach.d.ts +4 -0
  55. package/dist/integrations/attach.js +33 -54
  56. package/dist/integrations/attach.ts +50 -57
  57. package/dist/integrations/cli.d.ts +37 -0
  58. package/dist/integrations/cli.js +440 -0
  59. package/dist/integrations/cli.ts +543 -0
  60. package/dist/{core/files.d.ts → integrations/disk.d.ts} +16 -20
  61. package/dist/integrations/disk.js +435 -0
  62. package/dist/integrations/disk.ts +465 -0
  63. package/dist/integrations/generators/read.js +6 -6
  64. package/dist/integrations/generators/read.ts +4 -4
  65. package/dist/integrations/generators/vault.js +10 -11
  66. package/dist/integrations/generators/vault.ts +4 -5
  67. package/dist/{operations/http.d.ts → integrations/https.d.ts} +10 -6
  68. package/dist/integrations/https.js +170 -0
  69. package/dist/integrations/https.ts +216 -0
  70. package/dist/integrations/pglite.d.ts +26 -0
  71. package/dist/integrations/pglite.js +143 -0
  72. package/dist/integrations/pglite.ts +206 -0
  73. package/dist/integrations/secret.d.ts +8 -2
  74. package/dist/integrations/secret.js +3 -5
  75. package/dist/integrations/secret.ts +10 -6
  76. package/dist/integrations/target.d.ts +155 -14
  77. package/dist/integrations/target.js +171 -50
  78. package/dist/integrations/target.ts +377 -61
  79. package/dist/integrations/vault.d.ts +1 -0
  80. package/dist/integrations/vault.js +20 -5
  81. package/dist/integrations/vault.ts +17 -5
  82. package/dist/integrity/attach.js +3 -73
  83. package/dist/integrity/attach.ts +1 -71
  84. package/dist/integrity/check-threads.js +5 -5
  85. package/dist/integrity/check-threads.ts +2 -2
  86. package/dist/integrity/constraint.d.ts +0 -1
  87. package/dist/integrity/constraint.js +267 -366
  88. package/dist/integrity/constraint.ts +267 -375
  89. package/dist/integrity/generators/compiler.js +14 -17
  90. package/dist/integrity/generators/compiler.ts +10 -15
  91. package/dist/integrity/generators/gate.js +15 -15
  92. package/dist/integrity/generators/gate.ts +10 -10
  93. package/dist/integrity/generators/issues.js +7 -7
  94. package/dist/integrity/generators/publish.js +39 -57
  95. package/dist/integrity/generators/publish.ts +44 -55
  96. package/dist/integrity/generators/trial.d.ts +3 -3
  97. package/dist/integrity/generators/trial.js +133 -161
  98. package/dist/integrity/generators/trial.ts +145 -165
  99. package/dist/integrity/lint.js +9 -13
  100. package/dist/integrity/lint.ts +7 -10
  101. package/dist/integrity/lsp/bin.js +5 -4
  102. package/dist/integrity/lsp/bin.ts +3 -1
  103. package/dist/integrity/lsp/diagnostics.js +3 -3
  104. package/dist/integrity/lsp/diagnostics.ts +1 -1
  105. package/dist/integrity/lsp/lint.js +19 -30
  106. package/dist/integrity/lsp/lint.ts +16 -32
  107. package/dist/integrity/lsp/server.js +3 -3
  108. package/dist/integrity/slopnator.d.ts +3 -13
  109. package/dist/integrity/slopnator.js +58 -37
  110. package/dist/integrity/slopnator.ts +53 -37
  111. package/dist/integrity/slopnators/sl_broken_lineage.js +2 -2
  112. package/dist/integrity/slopnators/sl_declared_elsewhere.js +1 -1
  113. package/dist/integrity/slopnators/sl_derived_drift.js +4 -4
  114. package/dist/integrity/slopnators/sl_derived_drift.ts +1 -1
  115. package/dist/integrity/slopnators/sl_door_in_a_node.js +220 -0
  116. package/dist/integrity/slopnators/sl_door_in_a_node.ts +250 -0
  117. package/dist/integrity/slopnators/sl_inert_island.js +10 -8
  118. package/dist/integrity/slopnators/sl_inert_island.ts +8 -6
  119. package/dist/integrity/slopnators/sl_missing_row.js +6 -51
  120. package/dist/integrity/slopnators/sl_missing_row.ts +4 -50
  121. package/dist/integrity/slopnators/sl_no_barrel.js +1 -1
  122. package/dist/integrity/slopnators/sl_no_child_process.js +36 -18
  123. package/dist/integrity/slopnators/sl_no_child_process.ts +44 -18
  124. package/dist/integrity/slopnators/sl_no_dispatch_bypass.js +80 -149
  125. package/dist/integrity/slopnators/sl_no_dispatch_bypass.ts +95 -147
  126. package/dist/integrity/slopnators/sl_no_import_cycle.js +15 -4
  127. package/dist/integrity/slopnators/sl_no_import_cycle.ts +20 -4
  128. package/dist/integrity/slopnators/sl_no_such_command.js +2 -2
  129. package/dist/integrity/slopnators/sl_no_such_command.ts +1 -1
  130. package/dist/integrity/slopnators/sl_outside_an_operation.js +20 -0
  131. package/dist/integrity/slopnators/sl_outside_an_operation.ts +25 -0
  132. package/dist/integrity/slopnators/sl_screen_holds_only_declared.d.ts +2 -0
  133. package/dist/integrity/slopnators/sl_screen_holds_only_declared.js +61 -0
  134. package/dist/integrity/slopnators/sl_screen_holds_only_declared.ts +70 -0
  135. package/dist/integrity/slopnators/sl_secret_literal.js +1 -33
  136. package/dist/integrity/slopnators/sl_secret_literal.ts +1 -33
  137. package/dist/integrity/slopnators/sl_stale_path.js +5 -22
  138. package/dist/integrity/slopnators/sl_stale_path.ts +4 -20
  139. package/dist/integrity/slopnators/sl_twice_meant.js +1 -1
  140. package/dist/integrity/slopnators/sl_twice_parented.js +29 -5
  141. package/dist/integrity/slopnators/sl_twice_parented.ts +28 -4
  142. package/dist/integrity/slopnators/sl_undeclared_crossing.d.ts +4 -1
  143. package/dist/integrity/slopnators/sl_undeclared_crossing.js +426 -62
  144. package/dist/integrity/slopnators/sl_undeclared_crossing.ts +454 -70
  145. package/dist/integrity/slopnators/sl_undeclared_destination.js +59 -25
  146. package/dist/integrity/slopnators/sl_undeclared_destination.ts +69 -21
  147. package/dist/integrity/slopnators/sl_undeclared_list.d.ts +2 -0
  148. package/dist/integrity/slopnators/sl_undeclared_list.js +363 -0
  149. package/dist/integrity/slopnators/sl_undeclared_list.ts +358 -0
  150. package/dist/integrity/slopnators/sl_undeclared_node.js +1 -11
  151. package/dist/integrity/slopnators/sl_undeclared_node.ts +0 -10
  152. package/dist/integrity/slopnators/sl_undeclared_operation.js +111 -29
  153. package/dist/integrity/slopnators/sl_undeclared_operation.ts +134 -26
  154. package/dist/integrity/slopnators/sl_undeclared_variant.js +2 -2
  155. package/dist/integrity/slopnators/sl_undeclared_webhook.d.ts +2 -0
  156. package/dist/integrity/slopnators/sl_undeclared_webhook.js +90 -0
  157. package/dist/integrity/slopnators/sl_undeclared_webhook.ts +108 -0
  158. package/dist/integrity/slopnators/sl_underived_route.d.ts +2 -0
  159. package/dist/integrity/slopnators/sl_underived_route.js +61 -0
  160. package/dist/integrity/slopnators/sl_underived_route.ts +72 -0
  161. package/dist/integrity/slopnators/sl_ungoverned_island.js +3 -3
  162. package/dist/integrity/slopnators/sl_ungoverned_island.ts +1 -1
  163. package/dist/integrity/slopnators/sl_unlisted_program.d.ts +2 -0
  164. package/dist/integrity/slopnators/sl_unlisted_program.js +39 -0
  165. package/dist/integrity/slopnators/sl_unlisted_program.ts +40 -0
  166. package/dist/integrity/slopnators/sl_unnamed_island.js +1 -1
  167. package/dist/integrity/slopnators/sl_unpaired_member.js +3 -3
  168. package/dist/integrity/slopnators/sl_unpaired_member.ts +1 -1
  169. package/dist/integrity/slopnators/sl_unpaired_slopnator.js +4 -4
  170. package/dist/integrity/slopnators/sl_unpaired_slopnator.ts +1 -1
  171. package/dist/integrity/slopnators/sl_unprefixed_member.js +5 -31
  172. package/dist/integrity/slopnators/sl_unprefixed_member.ts +2 -28
  173. package/dist/integrity/slopnators/sl_unthreaded.js +11 -7
  174. package/dist/integrity/slopnators/sl_unthreaded.ts +6 -7
  175. package/dist/integrity/slopnators/sl_untranslated_key.js +2 -25
  176. package/dist/integrity/slopnators/sl_untranslated_key.ts +1 -25
  177. package/dist/integrity/slopnators/sl_unvaulted_secret.d.ts +2 -0
  178. package/dist/integrity/slopnators/sl_unvaulted_secret.js +107 -0
  179. package/dist/integrity/slopnators/sl_unvaulted_secret.ts +132 -0
  180. package/dist/integrity/slopnators/sl_unversioned.js +6 -4
  181. package/dist/integrity/slopnators/sl_unversioned.ts +5 -3
  182. package/dist/integrity/sweep.d.ts +1 -0
  183. package/dist/integrity/sweep.js +105 -42
  184. package/dist/integrity/sweep.ts +115 -42
  185. package/dist/knowledge/attach.js +1 -1
  186. package/dist/knowledge/generators/docsgen.js +8 -6
  187. package/dist/knowledge/generators/docsgen.ts +4 -2
  188. package/dist/knowledge/generators/glossary.js +4 -4
  189. package/dist/knowledge/generators/glossary.ts +1 -1
  190. package/dist/operations/access.d.ts +23 -0
  191. package/dist/operations/access.js +28 -1
  192. package/dist/operations/access.ts +43 -0
  193. package/dist/operations/attach.js +28 -109
  194. package/dist/operations/attach.ts +46 -113
  195. package/dist/operations/capabilities.d.ts +14 -5
  196. package/dist/operations/capabilities.js +13 -4
  197. package/dist/operations/capabilities.ts +27 -8
  198. package/dist/operations/dispatch.d.ts +8 -2
  199. package/dist/operations/dispatch.js +128 -185
  200. package/dist/operations/dispatch.ts +138 -191
  201. package/dist/operations/error-results.d.ts +1 -1
  202. package/dist/operations/error-results.js +2 -2
  203. package/dist/operations/error-results.ts +2 -2
  204. package/dist/operations/generators/capability.d.ts +11 -1
  205. package/dist/operations/generators/capability.js +481 -224
  206. package/dist/operations/generators/capability.ts +562 -233
  207. package/dist/operations/generators/compile.js +66 -39
  208. package/dist/operations/generators/compile.ts +78 -39
  209. package/dist/operations/generators/permits.js +11 -12
  210. package/dist/operations/generators/permits.ts +3 -4
  211. package/dist/operations/generators/seed.d.ts +1 -0
  212. package/dist/operations/generators/seed.js +19 -17
  213. package/dist/operations/generators/seed.ts +22 -14
  214. package/dist/operations/generators/trial.d.ts +6 -8
  215. package/dist/operations/generators/trial.js +200 -70
  216. package/dist/operations/generators/trial.ts +230 -93
  217. package/dist/operations/nodes.d.ts +15 -16
  218. package/dist/operations/nodes.ts +16 -17
  219. package/dist/operations/operations.d.ts +40 -4
  220. package/dist/operations/operations.js +1 -0
  221. package/dist/operations/operations.ts +61 -4
  222. package/dist/operations/result.d.ts +2 -2
  223. package/dist/operations/result.ts +2 -2
  224. package/package.json +1 -4
  225. package/dist/core/answers.d.ts +0 -171
  226. package/dist/core/answers.js +0 -789
  227. package/dist/core/answers.ts +0 -999
  228. package/dist/core/client.d.ts +0 -57
  229. package/dist/core/client.js +0 -247
  230. package/dist/core/client.ts +0 -286
  231. package/dist/core/files.js +0 -145
  232. package/dist/core/files.ts +0 -193
  233. package/dist/integrations/module.d.ts +0 -6
  234. package/dist/integrations/module.js +0 -153
  235. package/dist/integrations/module.ts +0 -191
  236. package/dist/integrity/slopnators/sl_unkept_rows.js +0 -104
  237. package/dist/integrity/slopnators/sl_unkept_rows.ts +0 -111
  238. package/dist/integrity/slopnators/sl_unseamed_reach.js +0 -73
  239. package/dist/integrity/slopnators/sl_unseamed_reach.ts +0 -79
  240. package/dist/operations/cost.d.ts +0 -14
  241. package/dist/operations/cost.js +0 -37
  242. package/dist/operations/cost.ts +0 -58
  243. package/dist/operations/errors/errors.d.ts +0 -52
  244. package/dist/operations/http.js +0 -124
  245. package/dist/operations/http.ts +0 -169
  246. package/dist/operations/memory.d.ts +0 -104
  247. package/dist/operations/memory.js +0 -365
  248. package/dist/operations/memory.ts +0 -470
  249. package/dist/operations/metering.d.ts +0 -55
  250. package/dist/operations/metering.js +0 -247
  251. package/dist/operations/metering.ts +0 -328
  252. package/dist/operations/queue-policy.d.ts +0 -3
  253. package/dist/operations/queue-policy.js +0 -8
  254. package/dist/operations/queue-policy.ts +0 -10
  255. package/dist/operations/seams.d.ts +0 -239
  256. package/dist/operations/seams.js +0 -45
  257. package/dist/operations/seams.ts +0 -364
  258. package/dist/operations/store.d.ts +0 -14
  259. package/dist/operations/store.js +0 -1
  260. package/dist/operations/store.ts +0 -29
  261. /package/dist/{operations → core}/errors/classes.d.ts +0 -0
  262. /package/dist/{operations → core}/errors/classes.js +0 -0
  263. /package/dist/{operations → core}/errors/classes.ts +0 -0
  264. /package/dist/integrity/slopnators/{sl_unkept_rows.d.ts → sl_door_in_a_node.d.ts} +0 -0
  265. /package/dist/integrity/slopnators/{sl_unseamed_reach.d.ts → sl_outside_an_operation.d.ts} +0 -0
@@ -1,14 +1,20 @@
1
1
  export declare const DISPATCH_AT = "operations/_dispatch.ts";
2
2
  export declare const dispatched: (reached: Readonly<Record<string, {
3
3
  readonly reach: string;
4
- readonly address: string | null;
4
+ readonly address?: string;
5
+ readonly headers: Readonly<Record<string, string>>;
5
6
  readonly sends: readonly {
6
7
  readonly secret: string;
7
8
  readonly header: string;
8
9
  readonly prefix: string;
9
10
  }[];
11
+ readonly signs: readonly {
12
+ readonly secret: string;
13
+ readonly header: string;
14
+ readonly prefix: string;
15
+ }[];
10
16
  readonly calls: Readonly<Record<string, {
11
- readonly method: string;
17
+ readonly method: string | null;
12
18
  readonly path: string;
13
19
  }>>;
14
20
  }>>) => string;
@@ -1,49 +1,52 @@
1
- import { ANONYMOUS, ENVIRONMENT } from "../core/actor.js";
2
- import { errorDefForResult } from "./error-results.js";
3
- import { DbConflict } from "./errors/errors.js";
4
- import { quoted, runtime } from "./generators/seed.js";
5
- import { SUPPLY } from "./seams.js";
1
+ import { ANONYMOUS, ENVIRONMENT } from '../core/actor.js';
2
+ import { HOLDS } from '../integrations/target.js';
3
+ import { PERMITS_AT } from './access.js';
4
+ import { DbConflict } from '../core/errors/catalogue.js';
5
+ import { beside, quoted, runtime } from './generators/seed.js';
6
+ const reaching = (holds) => Object.keys(HOLDS).filter((one) => holds(HOLDS[one]));
7
+ const KEEPS = reaching((one) => one.takes === 'entities');
8
+ const ANSWERS = reaching((one) => one.takes === null);
9
+ const RUNS = reaching((one) => one.takes === 'calls' && one.addressed === 'nothing');
10
+ const asked = (reaches) => reaches.map((one) => "reach === '" + one + "'").join(' || ');
6
11
  export const DISPATCH_AT = 'operations/_dispatch.ts';
7
- const identity = (code) => {
8
- const def = errorDefForResult(code);
9
- return { code: def.code, class: def.class };
10
- };
11
- const CODES = ['denied', 'invalid', 'rate_limited', 'feature_denied', 'quota_exceeded', 'error'];
12
12
  const REFUSAL = {
13
- denied: { said: 'not allowed', outcome: 'denied' },
14
- invalid: { said: 'invalid input', outcome: 'failed' },
15
- rate_limited: { said: 'rate limited', outcome: 'rate_limited' },
16
- feature_denied: { said: 'not in plan', outcome: 'feature_denied' },
17
- quota_exceeded: { said: 'quota exceeded', outcome: 'quota_exceeded' },
18
- error: { said: 'failed', outcome: 'failed' },
13
+ denied: 'not allowed',
14
+ invalid: 'invalid input',
15
+ rate_limited: 'rate limited',
16
+ feature_denied: 'not in plan',
17
+ quota_exceeded: 'quota exceeded',
18
+ error: 'failed',
19
19
  };
20
20
  const printed = (value) => JSON.stringify(value, null, 2);
21
- const DEFS = Object.fromEntries(CODES.map((code) => [code, identity(code)]));
22
21
  export const dispatched = (reached) => [
22
+ "import { createHmac } from 'node:crypto'",
23
+ '',
23
24
  `import type { Actor } from ${quoted(runtime(DISPATCH_AT, '../../core/actor.ts'))}`,
24
- `import type { Operation } from ${quoted(runtime(DISPATCH_AT, '../operations.ts'))}`,
25
+ `import type { Allowance, Counting, Operation } from ${quoted(runtime(DISPATCH_AT, '../operations.ts'))}`,
25
26
  `import type { FailureIdentity, Result, ResultCode } from ${quoted(runtime(DISPATCH_AT, '../result.ts'))}`,
26
- `import type { AuditOutcome, Handed, LogLevel, QuotaHold, Seams } from ${quoted(runtime(DISPATCH_AT, '../seams.ts'))}`,
27
+ 'import type { Opened } from ' + quoted(runtime(DISPATCH_AT, '../operations.ts')),
28
+ 'import type { Vault } from ' + quoted(runtime(DISPATCH_AT, '../../integrations/secret.ts')),
29
+ `import { permits } from ${quoted(beside(DISPATCH_AT, PERMITS_AT))}`,
27
30
  '',
28
31
  `const ANONYMOUS: Actor = ${printed(ANONYMOUS)}`,
29
32
  '',
30
33
  `const ENVIRONMENT: readonly string[] = ${printed(ENVIRONMENT.map(([fact]) => fact))}`,
31
34
  '',
32
- `const REFUSAL: Readonly<Record<ResultCode, { readonly said: string; readonly outcome: AuditOutcome }>> = ${printed(REFUSAL)}`,
33
- '',
34
- `const DEFS = ${printed(DEFS)} as Readonly<Record<ResultCode, FailureIdentity>>`,
35
+ `const REFUSAL: Readonly<Record<ResultCode, string>> = ${printed(REFUSAL)}`,
35
36
  '',
36
37
  `const CONFLICT = ${printed({ code: DbConflict.def.code, class: DbConflict.def.class })} as FailureIdentity`,
37
38
  '',
38
- `const SUPPLY: Readonly<Record<string, string>> = ${printed(SUPPLY)}`,
39
- '',
40
39
  'type Reached = Readonly<Record<string, {',
41
40
  ' readonly reach: string',
42
- ' readonly address: string | null',
41
+ ' readonly address?: string',
42
+ ' readonly headers: Readonly<Record<string, string>>',
43
43
  ' readonly sends: readonly { readonly secret: string; readonly header: string; readonly prefix: string }[]',
44
- ' readonly calls: Readonly<Record<string, { readonly method: string; readonly path: string }>>',
44
+ ' readonly signs: readonly { readonly secret: string; readonly header: string; readonly prefix: string }[]',
45
+ ' readonly calls: Readonly<Record<string, { readonly method: string | null; readonly path: string }>>',
45
46
  '}>>',
46
47
  '',
48
+ 'type Reaches = Readonly<Record<string, unknown>>',
49
+ '',
47
50
  `const REACHED: Reached = ${printed(reached)}`,
48
51
  '',
49
52
  "const STOPPED = Symbol.for('thread.operation.stopped')",
@@ -58,6 +61,22 @@ export const dispatched = (reached) => [
58
61
  ' ...(identity === undefined ? {} : { errorCode: identity.code, errorClass: identity.class }),',
59
62
  '}) as Result<never>',
60
63
  '',
64
+ 'const allowance = async (',
65
+ ' id: string,',
66
+ ' actor: Actor,',
67
+ ' counting: Counting | undefined,',
68
+ ' held: Allowance | undefined,',
69
+ ' code: ResultCode,',
70
+ '): Promise<Result<never> | undefined> => {',
71
+ ' if (held === undefined) return undefined',
72
+ ' if (counting === undefined) {',
73
+ " return fail('error', REFUSAL['error'], id + ' allows ' + String(held.runs) + ' run(s) per ' + held.per + ' and this dispatch was handed nothing to count with. An operation that states an allowance is handed a counter or it does not run')",
74
+ ' }',
75
+ " const seen = await counting['seen'](id + '/' + String(actor.id ?? 'anonymous') + '/' + code, held.per)",
76
+ ' if (seen <= held.runs) return undefined',
77
+ " return fail(code, REFUSAL[code], String(seen) + ' of ' + String(held.runs) + ' allowed per ' + held.per)",
78
+ '}',
79
+ '',
61
80
  "const strings = (value: unknown): value is string[] => Array.isArray(value) && value.every((one) => typeof one === 'string')",
62
81
  '',
63
82
  'const person = (value: unknown): Actor | undefined => {',
@@ -90,12 +109,6 @@ export const dispatched = (reached) => [
90
109
  " return one[STOPPED] === true ? { value: one['value'] } : undefined",
91
110
  '}',
92
111
  '',
93
- 'const marked = (thrown: unknown): string | undefined => {',
94
- " if (typeof thrown !== 'object' || thrown === null) return undefined",
95
- ' const said = (thrown as { readonly node?: unknown }).node',
96
- " return typeof said === 'string' ? said : undefined",
97
- '}',
98
- '',
99
112
  'const platform = (thrown: unknown): string | undefined => {',
100
113
  " if (typeof thrown !== 'object' || thrown === null) return undefined",
101
114
  ' const said = (thrown as { readonly because?: unknown }).because',
@@ -110,59 +123,88 @@ export const dispatched = (reached) => [
110
123
  ' return held',
111
124
  '}',
112
125
  '',
113
- 'const bound = (word: string, wired: Reached[string], seams: Seams): Record<string, unknown> | string => {',
126
+ 'const bound = (word: string, wired: Reached[string], opened: Reaches, opening: Vault | undefined, within: number): Record<string, unknown> | string => {',
127
+ ' const reached = opened[word]',
128
+ ' const { reach } = wired',
129
+ ' if (' + asked(ANSWERS) + ') {',
130
+ ' const held = reached',
131
+ ' if (held === undefined) {',
132
+ " return word + ' is a disk this operation requires, and this dispatch was handed none under that name. The disk under this process is written in by thread capabilities; one at the other end of a connection is handed in by whoever opened it'",
133
+ ' }',
134
+ ' return held as unknown as Record<string, unknown>',
135
+ ' }',
136
+ ' if (' + asked(KEEPS) + ') {',
137
+ ' if (reached === undefined) {',
138
+ " return word + ' keeps rows for this app, and this dispatch was handed no store. A store is written in by thread capabilities, out of the target that keeps the entity'",
139
+ ' }',
140
+ ' return reached as unknown as Record<string, unknown>',
141
+ ' }',
142
+ '',
114
143
  ' const names = Object.keys(wired.calls)',
115
144
  ' if (names.length === 0) {',
116
145
  ' return `\\`${word}\\` is required and takes no call, so there is nothing to hand a node. Declare one with \\`thread create target call\\``',
117
146
  ' }',
118
- ' if (seams.http === undefined) {',
119
- ' return `\\`${word}\\` is reached over ${wired.reach} and the seams this dispatch was handed hold no \\`http\\` — wire one, or take \\`${word}\\` off that operation\'s row`',
147
+ ' if (' + asked(RUNS) + ') {',
148
+ ' const held = reached',
149
+ ' if (held === undefined) {',
150
+ " return word + ' is a program this operation requires, and this dispatch was handed none under that name. A program is written in by thread capabilities, out of the calls declared beside the target'",
151
+ ' }',
152
+ ' const out: Record<string, unknown> = {}',
153
+ ' for (const name of names) {',
154
+ ' const doing = (held as unknown as Record<string, unknown>)[name]',
155
+ " if (typeof doing !== 'function') {",
156
+ " return word + ' takes ' + name + ' and the program handed in under that name does not answer to it, so a node would be handed a word that does nothing'",
157
+ ' }',
158
+ ' out[name] = (args: readonly string[], shows?: boolean, sooner?: number, how?: unknown) => (doing as (a: readonly string[], s?: boolean, w?: number, h?: unknown) => unknown)(args, shows, sooner === undefined ? within : Math.min(sooner, within), how)',
159
+ ' }',
160
+ ' return out',
161
+ ' }',
162
+ ' if (reached === undefined) {',
163
+ " return word + ' is reached over ' + wired.reach + ', and this dispatch was handed nothing to send an outward call through. thread capabilities writes that in; or take that word off the row that requires it'",
120
164
  ' }',
121
- ' const wanted = [...(wired.address === null ? [] : [wired.address]), ...wired.sends.map((one) => one.secret)]',
122
- ' if (wanted.length > 0 && seams.vault === undefined) {',
123
- ' return `\\`${word}\\` needs ${wanted.join(\', \')} and the seams this dispatch was handed hold no \\`vault\\` to open them. A target is reached with what opens it or not at all`',
165
+ ' const wanted = [...wired.sends.map((one) => one.secret), ...wired.signs.map((one) => one.secret)]',
166
+ ' if (wanted.length > 0 && opening === undefined) {',
167
+ " return word + ' needs ' + wanted.join(', ') + ' and this dispatch was handed no vault to open them. A target is reached with what opens it or not at all'",
124
168
  ' }',
125
169
  ' const out: Record<string, unknown> = {}',
126
170
  ' for (const name of names) {',
127
171
  ' const call = wired.calls[name]',
128
172
  ' if (call === undefined) continue',
129
- ' out[name] = async (given?: { fills?: Readonly<Record<string, string | number>>; json?: unknown; body?: Uint8Array; contentType?: string }) => {',
130
- ' const values = wanted.length === 0 ? {} : await seams.vault!.resolve(wanted)',
173
+ ' out[name] = async (given?: { fills?: Readonly<Record<string, string | number>>; json?: unknown; body?: Uint8Array; contentType?: string; told?: (said: unknown) => void }) => {',
174
+ " const values = wanted.length === 0 ? {} : await opening!['resolve'](wanted)",
131
175
  ' const headers: Record<string, string> = {}',
176
+ ' for (const [name, value] of Object.entries(wired.headers)) headers[name] = value',
132
177
  ' for (const one of wired.sends) headers[one.header] = `${one.prefix}${values[one.secret] ?? \'\'}`',
133
178
  ' const body = given?.json === undefined ? given?.body : new TextEncoder().encode(JSON.stringify(given.json))',
134
- ' return await seams.http!.call({',
179
+ ' for (const one of wired.signs) {',
180
+ " const mac = createHmac('sha256', values[one.secret] ?? '').update(body ?? new Uint8Array()).digest('hex')",
181
+ ' headers[one.header] = one.prefix + mac',
182
+ ' }',
183
+ " const send = reached as { call: (request: unknown, within?: number) => Promise<unknown> }",
184
+ " return await send['call']({",
135
185
  ' target: word,',
136
- ' address: wired.address === null ? \'\' : (values[wired.address] ?? \'\'),',
186
+ ' address: wired.address ?? \'\',',
137
187
  " method: call.method as 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE',",
138
188
  ' path: filled(call.path, given?.fills),',
139
189
  ' headers,',
140
190
  ' ...(body === undefined ? {} : { body, contentType: given?.contentType ?? \'application/json\' }),',
141
- ' })',
191
+ ' ...(given?.told === undefined ? {} : { told: given.told }),',
192
+ ' }, within)',
142
193
  ' }',
143
194
  ' }',
144
195
  ' return out',
145
196
  '}',
146
197
  '',
147
- 'const given = (operation: Operation<unknown, string>, actor: Actor, seams: Seams): Record<string, unknown> | string => {',
148
- ' const held: Record<string, unknown> = { actor }',
198
+ 'const given = (operation: Operation<unknown, string>, actor: Actor, opened: Reaches, opening: Vault | undefined, telling: (said: unknown) => void): Record<string, unknown> | string => {',
199
+ ' const held: Record<string, unknown> = { actor, tell: telling }',
149
200
  ' for (const word of operation.requires) {',
150
- ' const key = SUPPLY[word]',
151
- ' if (key === undefined) {',
152
- ' const wired = REACHED[word]',
153
- ' if (wired === undefined) {',
154
- ' return `\\`${operation.id}\\` requires \\`${word}\\`, and nothing here supplies it — what may be required is ${[...Object.keys(SUPPLY), ...Object.keys(REACHED)].join(\', \')}`',
155
- ' }',
156
- ' const reached = bound(word, wired, seams)',
157
- " if (typeof reached === 'string') return reached",
158
- ' held[word] = reached',
159
- ' continue',
160
- ' }',
161
- ' const seam = (seams as unknown as Record<string, unknown>)[key]',
162
- ' if (seam === undefined) {',
163
- ' return `\\`${operation.id}\\` requires \\`${word}\\`, and the seams this dispatch was handed hold no \\`${key}\\` — wire one, or take \\`${word}\\` off that operation\'s row. An operation does not run short of what it declared`',
201
+ ' const wired = REACHED[word]',
202
+ ' if (wired === undefined) {',
203
+ ' return `\\`${operation[\'id\']}\\` requires \\`${word}\\`, and this app declares no target by that name. An operation requires targets: declare one with \\`thread create target\\`, or take that word off its row`',
164
204
  ' }',
165
- ' held[key] = seam',
205
+ ' const reached = bound(word, wired, opened, opening, operation.timeout)',
206
+ " if (typeof reached === 'string') return reached",
207
+ ' held[word] = reached',
166
208
  ' }',
167
209
  ' return held',
168
210
  '}',
@@ -171,155 +213,56 @@ export const dispatched = (reached) => [
171
213
  ' operation: Operation<I, R>,',
172
214
  ' rawInput: unknown,',
173
215
  ' asking: Actor,',
174
- ' seams: Seams,',
216
+ ' opened: Reaches,',
217
+ ' opening: Vault | undefined,',
218
+ ' counting?: Counting,',
219
+ ' telling?: (said: unknown) => void,',
175
220
  '): Promise<Result<unknown>> {',
176
221
  ' const id = operation.id',
177
222
  ' const who = person(asking)',
178
- ' const run = who?.run ?? seams.random.uuid()',
179
- ' const actor: Actor = { ...(who ?? ANONYMOUS), run }',
180
- ' const span = seams.telemetry?.start(id, run, { ...actor })',
181
- '',
182
- ' const gates = { rate: seams.rateLimiter !== undefined, replay: seams.idempotency !== undefined, quota: seams.quotas !== undefined, telemetry: seams.telemetry !== undefined }',
183
- '',
184
- ' let hold: QuotaHold | null = null',
185
- ' let granted: string | undefined',
186
- '',
187
- ' const sank = (what: string) => (thrown: unknown): void => {',
188
- " seams.log.write('error', id, actor, {",
189
- ' [`${what}_failed`]: thrown instanceof Error ? thrown.message : String(thrown),',
190
- ' })',
191
- ' }',
192
- '',
193
- ' const settled = async (held: Result<unknown>, because?: string): Promise<Result<unknown>> => {',
194
- " const outcome: AuditOutcome = held.ok ? 'ok' : REFUSAL[held.code].outcome",
195
- ' const detail = because === undefined ? {} : { because }',
196
- '',
197
- ' const reserved = hold === null ? null : operation.estimate',
198
- ' let consumed: number | null = null',
199
- '',
200
- ' if (hold !== null) {',
201
- ' const settling = held.ok ? hold.commit(operation.estimate) : hold.release()',
202
- ' consumed = held.ok ? operation.estimate : 0',
203
- ' hold = null',
204
- " await settling.catch(sank('quota'))",
205
- ' }',
206
- '',
207
- " seams.log.write(held.ok ? 'info' : 'warn', id, actor, {",
208
- ' outcome,',
209
- ' ...detail,',
210
- " access: { roles: actor.roles, entitlements: actor.entitlements, granted: granted ?? 'not reached' },",
211
- ' quota: { meter: id, reserved, consumed },',
212
- ' gates,',
213
- ' })',
214
- ' if (held.ok) span?.ok()',
215
- ' else span?.error(outcome)',
216
- '',
217
- ' await seams.audit',
218
- " .append(actor, { action: id, outcome, subject: { type: 'operation', id }, ...detail })",
219
- " .catch(sank('audit'))",
220
- '',
221
- ' if (!held.ok) {',
222
- ' const identity: FailureIdentity =',
223
- ' held.errorCode === undefined || held.errorClass === undefined',
224
- ' ? DEFS[held.code]',
225
- ' : { code: held.errorCode, class: held.errorClass }',
226
- '',
227
- ' await seams.errors',
228
- ' .record(actor, { code: identity.code, class: identity.class, action: id, ...detail })',
229
- " .catch(sank('errors'))",
230
- ' }',
231
- '',
232
- ' return held',
233
- ' }',
234
- '',
235
- ' const refused = (code: ResultCode, because?: string): Promise<Result<unknown>> =>',
236
- ' settled(fail(code, REFUSAL[code].said, because), because)',
237
- '',
238
- ' const recorded = (began: number, ok: boolean, at: string | undefined, because?: string): void => {',
239
- ' const took = seams.clock.now() - began',
240
- ' const sections = {',
241
- ' node: { at: at ?? null },',
242
- ' audit: { actor, when: began },',
243
- ' observability: { ms: took, ok, ...(because === undefined ? {} : { because }) },',
244
- ' }',
245
- '',
246
- " seams.log.write(ok ? 'info' : 'warn', id, actor, sections)",
247
- ' seams.telemetry?.record?.({',
248
- ' key: id,',
249
- ' traceId: run,',
250
- ' spanId: run,',
251
- ' durationMs: took,',
252
- ' ok,',
253
- ' attrs: sections,',
254
- ' actor,',
255
- ' ...(at === undefined ? {} : { nodeId: at }),',
256
- ' workflowId: id,',
257
- ' ...(because === undefined ? {} : { error: because }),',
258
- ' })',
259
- ' }',
260
- '',
223
+ ' const actor: Actor = who ?? ANONYMOUS',
261
224
  ' try {',
262
- " if (who === undefined) return await refused('denied', 'identity_invalid')",
263
- '',
264
- " if (seams.rateLimiter !== undefined && !(await seams.rateLimiter.check(actor, id))) return await refused('rate_limited')",
265
- '',
266
- ' const replayed = seams.idempotency === undefined ? null : await seams.idempotency.check(actor.replay, id)',
267
- " if (replayed !== null && replayed !== undefined) return await settled(ok(replayed), 'replayed')",
268
- '',
225
+ " if (who === undefined) return fail('denied', REFUSAL['denied'], 'identity_invalid')",
269
226
  ' const parsed = operation.input.safeParse(rawInput)',
270
227
  ' if (!parsed.success) {',
271
- " return await refused('invalid', parsed.error.issues.map((one) => one.message).join('; '))",
228
+ " return fail('invalid', REFUSAL['invalid'], String(parsed['error']))",
272
229
  ' }',
273
- '',
274
- ' if (seams.quotas) {',
275
- ' const reserved = await seams.quotas.reserve(actor, id, operation.estimate)',
276
- " if (!reserved.ok) return await refused('quota_exceeded', reserved.behavior ?? 'block')",
277
- ' hold = reserved',
278
- ' }',
279
- '',
280
- ' if (seams.permits === undefined) {',
281
- " return await refused('denied', 'no permits check is wired, so nothing can permit this operation')",
230
+ ' const { resource } = operation',
231
+ ' const ruled = permits(actor, id, resource(parsed[\'data\']))',
232
+ ' const { allow, because: why } = ruled',
233
+ " if (!allow) return fail('denied', REFUSAL['denied'], why)",
234
+ '',
235
+ ' const { entitled } = operation',
236
+ ' if (entitled !== undefined && !actor.entitlements.includes(entitled)) {',
237
+ " return fail('feature_denied', REFUSAL['feature_denied'], id + ' is offered on ' + entitled + ', which this caller does not hold')",
282
238
  ' }',
283
239
  '',
284
- ' const ruled = await seams.permits.check(actor, id, operation.resource(parsed.data))',
285
- " if (!ruled.allow) return await refused('denied', ruled.because)",
286
- ' granted = ruled.because',
240
+ " const limited = await allowance(id, actor, counting, operation.rate, 'rate_limited')",
241
+ ' if (limited !== undefined) return limited',
242
+ " const over = await allowance(id, actor, counting, operation.quota, 'quota_exceeded')",
243
+ ' if (over !== undefined) return over',
287
244
  '',
288
- ' const hands = given(operation as Operation<unknown, string>, actor, seams)',
289
- " if (typeof hands === 'string') return await refused('error', hands)",
245
+ ' const handed = given(operation as Operation<unknown, string>, actor, opened, opening, telling ?? (() => undefined))',
246
+ " if (typeof handed === 'string') return fail('error', REFUSAL['error'], handed)",
290
247
  '',
291
248
  ' const held: { readonly input: I } & Record<string, unknown> = { input: parsed.data }',
292
- ' const began = seams.clock.now()',
293
- ' let value: unknown',
294
- ' try {',
295
- ' value = await operation.run(hands as Handed<R>, held)',
296
- ' } catch (thrown) {',
297
- ' recorded(began, stopped(thrown) !== undefined, marked(thrown), thrown instanceof Error ? thrown.message : String(thrown))',
298
- ' throw thrown',
299
- ' }',
300
- ' recorded(began, true, undefined)',
301
- '',
302
- " if (seams.idempotency !== undefined) await seams.idempotency.store(actor.replay, id, value).catch(sank('idempotency'))",
303
- '',
304
- ' return await settled(ok(value))',
249
+ ' const value = await operation.run(handed as Opened<R>, held)',
250
+ ' return ok(value)',
305
251
  ' } catch (thrown) {',
306
252
  ' const early = stopped(thrown)',
307
253
  ' if (early !== undefined) {',
308
- " if (seams.idempotency !== undefined) await seams.idempotency.store(actor.replay, id, early.value).catch(sank('idempotency'))",
309
- " return await settled(ok(early.value), 'stopped')",
254
+ ' return ok(early[\'value\'])',
310
255
  ' }',
311
256
  '',
312
257
  ' const message = thrown instanceof Error ? thrown.message : String(thrown)',
313
258
  '',
314
259
  " if (named(thrown, 'VersionConflictError')) {",
315
- " return await settled(fail('invalid', message, 'version_conflict', CONFLICT), 'version_conflict')",
260
+ " return fail('invalid', message, 'version_conflict', CONFLICT)",
316
261
  ' }',
317
262
  '',
318
263
  " const code: ResultCode = named(thrown, 'ValidationError') ? 'invalid' : 'error'",
319
264
  ' const because = platform(thrown) ?? message',
320
- ' return await settled(fail(code, message, because), because)',
321
- ' } finally {',
322
- ' span?.end()',
265
+ ' return fail(code, message, because)',
323
266
  ' }',
324
267
  '}',
325
268
  '',