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