@agenticprimitives/fabric 0.0.0-alpha.4 → 0.0.0-alpha.8
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/CLAUDE.md +22 -2
- package/README.md +16 -16
- package/dist/case-emissions.d.ts +95 -0
- package/dist/case-emissions.d.ts.map +1 -0
- package/dist/case-emissions.js +208 -0
- package/dist/case-emissions.js.map +1 -0
- package/dist/case-machine.d.ts +28 -2
- package/dist/case-machine.d.ts.map +1 -1
- package/dist/case-machine.js +34 -7
- package/dist/case-machine.js.map +1 -1
- package/dist/cloudflare/index.d.ts +1 -0
- package/dist/cloudflare/index.d.ts.map +1 -1
- package/dist/cloudflare/index.js +4 -0
- package/dist/cloudflare/index.js.map +1 -1
- package/dist/cloudflare/interaction-store.d.ts +55 -0
- package/dist/cloudflare/interaction-store.d.ts.map +1 -0
- package/dist/cloudflare/interaction-store.js +230 -0
- package/dist/cloudflare/interaction-store.js.map +1 -0
- package/dist/cloudflare/principal-gateway-do.d.ts +118 -2
- package/dist/cloudflare/principal-gateway-do.d.ts.map +1 -1
- package/dist/cloudflare/principal-gateway-do.js +182 -7
- package/dist/cloudflare/principal-gateway-do.js.map +1 -1
- package/dist/communicative-act.d.ts +24 -1
- package/dist/communicative-act.d.ts.map +1 -1
- package/dist/communicative-act.js +28 -0
- package/dist/communicative-act.js.map +1 -1
- package/dist/delivery-envelope.d.ts.map +1 -1
- package/dist/delivery-envelope.js +0 -1
- package/dist/delivery-envelope.js.map +1 -1
- package/dist/enum-retirement.d.ts +43 -0
- package/dist/enum-retirement.d.ts.map +1 -0
- package/dist/enum-retirement.js +93 -0
- package/dist/enum-retirement.js.map +1 -0
- package/dist/exchange-record.d.ts +35 -4
- package/dist/exchange-record.d.ts.map +1 -1
- package/dist/exchange-record.js.map +1 -1
- package/dist/exchange-reducer.d.ts +32 -4
- package/dist/exchange-reducer.d.ts.map +1 -1
- package/dist/exchange-reducer.js +75 -1
- package/dist/exchange-reducer.js.map +1 -1
- package/dist/exchange-state.d.ts +30 -8
- package/dist/exchange-state.d.ts.map +1 -1
- package/dist/exchange-state.js +12 -10
- package/dist/exchange-state.js.map +1 -1
- package/dist/inbox-doc.d.ts +2 -2
- package/dist/inbox-doc.d.ts.map +1 -1
- package/dist/inbox-doc.js.map +1 -1
- package/dist/inbox-projection.d.ts +2 -2
- package/dist/inbox-projection.d.ts.map +1 -1
- package/dist/inbox-projection.js.map +1 -1
- package/dist/index.d.ts +21 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +32 -2
- package/dist/index.js.map +1 -1
- package/dist/interaction-machines.d.ts +136 -0
- package/dist/interaction-machines.d.ts.map +1 -0
- package/dist/interaction-machines.js +174 -0
- package/dist/interaction-machines.js.map +1 -0
- package/dist/interaction-profile.d.ts +126 -0
- package/dist/interaction-profile.d.ts.map +1 -0
- package/dist/interaction-profile.js +192 -0
- package/dist/interaction-profile.js.map +1 -0
- package/dist/interaction-record.d.ts +168 -0
- package/dist/interaction-record.d.ts.map +1 -0
- package/dist/interaction-record.js +108 -0
- package/dist/interaction-record.js.map +1 -0
- package/dist/interactions/machine.d.ts +2 -2
- package/dist/interactions/machine.d.ts.map +1 -1
- package/dist/interactions/machine.js +2 -2
- package/dist/interactions/machine.js.map +1 -1
- package/dist/interactions/store.d.ts +9 -0
- package/dist/interactions/store.d.ts.map +1 -1
- package/dist/interactions/store.js +57 -2
- package/dist/interactions/store.js.map +1 -1
- package/dist/messaging/board.d.ts +3 -3
- package/dist/messaging/board.d.ts.map +1 -1
- package/dist/messaging/board.js +2 -2
- package/dist/messaging/board.js.map +1 -1
- package/dist/messaging/conversation-interaction.d.ts +66 -0
- package/dist/messaging/conversation-interaction.d.ts.map +1 -0
- package/dist/messaging/conversation-interaction.js +139 -0
- package/dist/messaging/conversation-interaction.js.map +1 -0
- package/dist/messaging/delivery.d.ts +2 -2
- package/dist/messaging/delivery.d.ts.map +1 -1
- package/dist/messaging/delivery.js +8 -1
- package/dist/messaging/delivery.js.map +1 -1
- package/dist/messaging/envelope.d.ts +7 -3
- package/dist/messaging/envelope.d.ts.map +1 -1
- package/dist/messaging/envelope.js +18 -1
- package/dist/messaging/envelope.js.map +1 -1
- package/dist/messaging/hash.d.ts +8 -2
- package/dist/messaging/hash.d.ts.map +1 -1
- package/dist/messaging/hash.js +6 -0
- package/dist/messaging/hash.js.map +1 -1
- package/dist/messaging/inbox-assistant.d.ts +16 -4
- package/dist/messaging/inbox-assistant.d.ts.map +1 -1
- package/dist/messaging/inbox-assistant.js +27 -4
- package/dist/messaging/inbox-assistant.js.map +1 -1
- package/dist/messaging/index.d.ts +4 -1
- package/dist/messaging/index.d.ts.map +1 -1
- package/dist/messaging/index.js +4 -0
- package/dist/messaging/index.js.map +1 -1
- package/dist/messaging/projector.d.ts +3 -3
- package/dist/messaging/projector.d.ts.map +1 -1
- package/dist/messaging/projector.js.map +1 -1
- package/dist/messaging/receipts.d.ts +3 -3
- package/dist/messaging/receipts.d.ts.map +1 -1
- package/dist/messaging/receipts.js.map +1 -1
- package/dist/messaging/rules.d.ts +10 -3
- package/dist/messaging/rules.d.ts.map +1 -1
- package/dist/messaging/rules.js +8 -1
- package/dist/messaging/rules.js.map +1 -1
- package/dist/messaging/store.d.ts +4 -4
- package/dist/messaging/store.d.ts.map +1 -1
- package/dist/messaging/store.js +5 -3
- package/dist/messaging/store.js.map +1 -1
- package/dist/messaging/types.d.ts +30 -0
- package/dist/messaging/types.d.ts.map +1 -1
- package/dist/messaging/types.js +3 -0
- package/dist/messaging/types.js.map +1 -1
- package/dist/messaging/vault-store.d.ts +2 -2
- package/dist/messaging/vault-store.d.ts.map +1 -1
- package/dist/protocol-binding.d.ts +71 -0
- package/dist/protocol-binding.d.ts.map +1 -0
- package/dist/protocol-binding.js +0 -0
- package/dist/protocol-binding.js.map +1 -0
- package/dist/record-catalog.d.ts.map +1 -1
- package/dist/record-catalog.js +7 -0
- package/dist/record-catalog.js.map +1 -1
- package/package.json +7 -7
package/CLAUDE.md
CHANGED
|
@@ -20,8 +20,28 @@ adapter ships from `./cloudflare`.
|
|
|
20
20
|
`@cloudflare/workers-types`.
|
|
21
21
|
- **W4 DONE:** `GatewaySurfaceCommitmentV1` (gatewayRoot preimage) + peer `DeliveryEnvelopeV1` +
|
|
22
22
|
`receiveDelivery` + `OutboxStore` store-and-forward.
|
|
23
|
-
- **
|
|
24
|
-
|
|
23
|
+
- **W6 DONE (spec 340 — the Agentic Interaction spine):** `apix:` is the canonical vocabulary
|
|
24
|
+
(`apfab:` RETIRED). `InteractionRecordV1` is the root aggregate; `ContextSnapshotV1` replaces
|
|
25
|
+
floating `contextRefs`; six state machines, never collapsed (delivery · inbox · interaction ·
|
|
26
|
+
decision · commitment · execution); versioned `InteractionProfile`s replace the `MessageKind`/
|
|
27
|
+
`CaseState` enums; `createDurableObjectInteractionStore` is their durable home on the gateway DO,
|
|
28
|
+
reachable as `do.interactions`. **The store exposes transitions, never state assignment** — the
|
|
29
|
+
creditor discharges, not the debtor, and persistence must not become a bypass.
|
|
30
|
+
- **W10a DONE (spec 340):** the case flow EMITS. `caseTransitionEmissions` + `applyCaseEmissions` put
|
|
31
|
+
`approve`/`deny`/`expire` into the decision machine and `issue-credential`/`revoke` into the
|
|
32
|
+
commitment machine, applied THROUGH those machines (never state assignment), wired into the
|
|
33
|
+
interaction store the Home drives. `deliver-credential` deliberately emits nothing — completing the
|
|
34
|
+
work discharges no obligation (ADR-0058 §15).
|
|
35
|
+
- **W10b DONE (spec 340):** `CaseState` is EXECUTION-ONLY (11 → 8). `approved`/`denied`/`expired`/
|
|
36
|
+
`revoked` removed, `closed` added. The transition VERBS are unchanged — which is why stored logs
|
|
37
|
+
replay untouched and no migration exists. `issue-credential`'s ordering is now a cross-machine
|
|
38
|
+
precondition (`requires-granted-decision`), projected onto `ExchangeRecordV1.decision` for the
|
|
39
|
+
reducer path, because that path had been getting the guarantee free from the FSM edge.
|
|
40
|
+
- **Next:** `MessageEnvelopeV1.kind` — the LAST enum, and the hard one: it is inside the signed wire
|
|
41
|
+
hash, so removal is an `ap.message.v2` cutover with re-signing, not a cleanup (spec 340 §R.1/§R.3); an interaction-aware ingress that
|
|
42
|
+
opens/joins an Interaction rather than only writing an Exchange; on-chain `atl:gatewayRoot` record
|
|
43
|
+
(contracts, separate); `A2aTaskDO`/`SessionStoreDO` absorption + `alarm()` drain; `fetch`/`alarm`
|
|
44
|
+
e2e via vitest-pool-workers.
|
|
25
45
|
|
|
26
46
|
## What this package owns
|
|
27
47
|
- `ExchangeRecordV1` — the ONE canonical object (spine id `xch_`); two-level FSM: `ExecState`
|
package/README.md
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
# @agenticprimitives/fabric
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
(
|
|
5
|
-
|
|
3
|
+
Ring-0 **operational** realization of Agentic Interaction. Semantics live under `apix:`
|
|
4
|
+
([ADR-0058](../../docs/architecture/decisions/0058-agentic-interaction-canonical-bounded-context.md) ·
|
|
5
|
+
[spec 340](../../specs/340-agentic-interaction.md)); this package owns wire types, reducers, and the
|
|
6
|
+
Cloudflare gateway adapter — not the ontology namespace (`apfab:` retired).
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
transport). The inbox is a projection (`projectInboxItem`).
|
|
11
|
-
- **Subpaths:** `@agenticprimitives/fabric/messaging` + `/interactions` re-export the absorbed surfaces.
|
|
8
|
+
Runtime doctrine still [spec 316](../../specs/316-agentic-interaction-fabric.md) /
|
|
9
|
+
[ADR-0047](../../docs/architecture/decisions/0047-agent-exchange-fabric-a2a-native.md): A2A-native
|
|
10
|
+
substrate absorbing messaging + interactions into one exchange object over a two-level exec/case FSM.
|
|
12
11
|
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
- **Exchange:** `ExchangeRecordV1` — `ExecState` + optional `CaseState`, fail-closed coupling.
|
|
13
|
+
- **Interaction (spec 340):** `InteractionRecordV1` + profiles + context snapshots on
|
|
14
|
+
`PrincipalGatewayDO` — **in package; apps still use demo-a2a `InteractionsDO` + vault board**.
|
|
15
|
+
- **Subpaths:** `@agenticprimitives/fabric/messaging` + `/interactions`.
|
|
15
16
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
[
|
|
21
|
-
[`docs/fabric-capability-gaps.md`](docs/fabric-capability-gaps.md).
|
|
17
|
+
Authority is never satisfied by the exchange (ADR-0041).
|
|
18
|
+
|
|
19
|
+
**Start here for app wiring + adoption matrix:** [`docs/architecture.md`](docs/architecture.md).
|
|
20
|
+
Also: `CLAUDE.md` · [target architecture](../../docs/architecture/agentic-interaction-fabric-target.md) ·
|
|
21
|
+
[commercial comparison](docs/fabric-capabilities-vs-commercial.md) · [gaps](docs/fabric-capability-gaps.md).
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import type { CanonicalAgentId } from '@agenticprimitives/types';
|
|
2
|
+
import type { CommitmentRecordV1, CommitmentTransition, DecisionRecordV1, DecisionTransition, MachineRejection } from './interaction-machines.js';
|
|
3
|
+
import type { CaseFsmFields, CaseTransition, CaseTransitionEventV1 } from './case-machine.js';
|
|
4
|
+
/**
|
|
5
|
+
* A record this emission needs to exist before its transition can land, given in its INITIAL state.
|
|
6
|
+
*
|
|
7
|
+
* Both machines refuse a transition out of a state the record is not in — `grant` is `pending →
|
|
8
|
+
* granted`, `void` is `proposed|active → void`. So an emission that only carried a transition would be
|
|
9
|
+
* unapplicable on the first move of a case that never had a decision record. The applier creates the
|
|
10
|
+
* record if absent, in exactly this state, and then applies the transition through the machine. It
|
|
11
|
+
* does NOT create it in the resulting state; that would be the state-assignment bypass this module
|
|
12
|
+
* exists to avoid.
|
|
13
|
+
*/
|
|
14
|
+
export interface DecisionSeedV1 {
|
|
15
|
+
decisionId: string;
|
|
16
|
+
decider: CanonicalAgentId;
|
|
17
|
+
subject: string;
|
|
18
|
+
expiresAt?: string;
|
|
19
|
+
}
|
|
20
|
+
export interface CommitmentSeedV1 {
|
|
21
|
+
commitmentId: string;
|
|
22
|
+
debtor: CanonicalAgentId;
|
|
23
|
+
creditor: CanonicalAgentId;
|
|
24
|
+
}
|
|
25
|
+
export interface CaseEmissionsV1 {
|
|
26
|
+
decision?: {
|
|
27
|
+
seed: DecisionSeedV1;
|
|
28
|
+
transition: DecisionTransition;
|
|
29
|
+
createIfAbsent: boolean;
|
|
30
|
+
};
|
|
31
|
+
commitment?: {
|
|
32
|
+
seed: CommitmentSeedV1;
|
|
33
|
+
transition: CommitmentTransition;
|
|
34
|
+
createIfAbsent: boolean;
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Deterministic ids, derived from the case id.
|
|
39
|
+
*
|
|
40
|
+
* Deliberately not random and not clock-derived: a case transition may be replayed (the interaction
|
|
41
|
+
* store is idempotent on `idempotencyKey`, and `processDue` re-runs sweeps), and a fresh id per replay
|
|
42
|
+
* would fork one determination into several. Same case ⇒ same decision ⇒ the second application is a
|
|
43
|
+
* no-op against a terminal state rather than a duplicate record.
|
|
44
|
+
*/
|
|
45
|
+
export declare function decisionIdForCase(caseId: string): string;
|
|
46
|
+
export declare function commitmentIdForCase(caseId: string): string;
|
|
47
|
+
/**
|
|
48
|
+
* Derive what a case transition emits. Pure, and total over `CaseTransition` — a transition with no
|
|
49
|
+
* emission returns `{}` rather than throwing, because most transitions genuinely emit nothing.
|
|
50
|
+
*
|
|
51
|
+
* Call this only for a transition the case machine ACCEPTED. It does not re-check legality: duplicating
|
|
52
|
+
* the case machine's role and ordering rules here would create a second, quietly diverging copy of them.
|
|
53
|
+
*/
|
|
54
|
+
export declare function caseTransitionEmissions(current: CaseFsmFields, event: CaseTransitionEventV1): CaseEmissionsV1;
|
|
55
|
+
/** The case transitions that emit something. Exported so a test can assert the set rather than
|
|
56
|
+
* restate it, and so a newly-added emitting transition shows up in a diff of this constant. */
|
|
57
|
+
export declare const EMITTING_CASE_TRANSITIONS: readonly CaseTransition[];
|
|
58
|
+
/** Seed a decision record in its INITIAL state. Never the resulting state — see `DecisionSeedV1`. */
|
|
59
|
+
export declare function seedDecision(seed: DecisionSeedV1, at: string): DecisionRecordV1;
|
|
60
|
+
/** Seed a commitment record in its INITIAL state. */
|
|
61
|
+
export declare function seedCommitment(seed: CommitmentSeedV1, at: string): CommitmentRecordV1;
|
|
62
|
+
/** Why an emission produced no record. `absent` is the deliberate `void`-without-a-commitment case;
|
|
63
|
+
* the others are the owning machine's own typed rejection, surfaced rather than swallowed. */
|
|
64
|
+
export type EmissionOutcome<T> = {
|
|
65
|
+
applied: true;
|
|
66
|
+
record: T;
|
|
67
|
+
} | {
|
|
68
|
+
applied: false;
|
|
69
|
+
reason: MachineRejection | 'absent';
|
|
70
|
+
};
|
|
71
|
+
export interface CaseEmissionApplyResult {
|
|
72
|
+
decision?: EmissionOutcome<DecisionRecordV1>;
|
|
73
|
+
commitment?: EmissionOutcome<CommitmentRecordV1>;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Apply emissions through the OWNING machines.
|
|
77
|
+
*
|
|
78
|
+
* The point of this function is what it does not do: it never assigns a state. A record is created
|
|
79
|
+
* only in its initial state and every move goes through `applyDecisionTransition` /
|
|
80
|
+
* `applyCommitmentTransition`, so their role and ordering checks still hold — the creditor still
|
|
81
|
+
* voids, the decider still decides.
|
|
82
|
+
*
|
|
83
|
+
* Rejections are RETURNED, not thrown and not swallowed. A caller that persists these must treat a
|
|
84
|
+
* rejected emission as a fact about the record it failed to write, because a silent no-op here is
|
|
85
|
+
* indistinguishable from success and would leave a case whose determination was never recorded
|
|
86
|
+
* looking exactly like one whose determination was.
|
|
87
|
+
*/
|
|
88
|
+
export declare function applyCaseEmissions(emissions: CaseEmissionsV1, existing: {
|
|
89
|
+
decision: DecisionRecordV1 | null;
|
|
90
|
+
commitment: CommitmentRecordV1 | null;
|
|
91
|
+
}, event: {
|
|
92
|
+
actor: CanonicalAgentId;
|
|
93
|
+
at: string;
|
|
94
|
+
}): CaseEmissionApplyResult;
|
|
95
|
+
//# sourceMappingURL=case-emissions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"case-emissions.d.ts","sourceRoot":"","sources":["../src/case-emissions.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAEjE,OAAO,KAAK,EACV,kBAAkB,EAClB,oBAAoB,EACpB,gBAAgB,EAChB,kBAAkB,EAClB,gBAAgB,EAEjB,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAE9F;;;;;;;;;GASG;AACH,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,gBAAgB,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,gBAAgB,CAAC;IACzB,QAAQ,EAAE,gBAAgB,CAAC;CAC5B;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE;QAAE,IAAI,EAAE,cAAc,CAAC;QAAC,UAAU,EAAE,kBAAkB,CAAC;QAAC,cAAc,EAAE,OAAO,CAAA;KAAE,CAAC;IAC7F,UAAU,CAAC,EAAE;QAAE,IAAI,EAAE,gBAAgB,CAAC;QAAC,UAAU,EAAE,oBAAoB,CAAC;QAAC,cAAc,EAAE,OAAO,CAAA;KAAE,CAAC;CACpG;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAExD;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAE1D;AAqGD;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,aAAa,EACtB,KAAK,EAAE,qBAAqB,GAC3B,eAAe,CAmBjB;AAED;gGACgG;AAChG,eAAO,MAAM,yBAAyB,EAAE,SAAS,cAAc,EAE1C,CAAC;AAEtB,qGAAqG;AACrG,wBAAgB,YAAY,CAAC,IAAI,EAAE,cAAc,EAAE,EAAE,EAAE,MAAM,GAAG,gBAAgB,CAS/E;AAED,qDAAqD;AACrD,wBAAgB,cAAc,CAAC,IAAI,EAAE,gBAAgB,EAAE,EAAE,EAAE,MAAM,GAAG,kBAAkB,CAQrF;AAED;+FAC+F;AAC/F,MAAM,MAAM,eAAe,CAAC,CAAC,IACzB;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,CAAC,CAAA;CAAE,GAC5B;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,gBAAgB,GAAG,QAAQ,CAAA;CAAE,CAAC;AAE5D,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,EAAE,eAAe,CAAC,gBAAgB,CAAC,CAAC;IAC7C,UAAU,CAAC,EAAE,eAAe,CAAC,kBAAkB,CAAC,CAAC;CAClD;AAeD;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,eAAe,EAC1B,QAAQ,EAAE;IAAE,QAAQ,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAAC,UAAU,EAAE,kBAAkB,GAAG,IAAI,CAAA;CAAE,EACtF,KAAK,EAAE;IAAE,KAAK,EAAE,gBAAgB,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAC7C,uBAAuB,CAsBzB"}
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
// spec 340 W10 — what a case transition EMITS into the decision and commitment machines.
|
|
2
|
+
//
|
|
3
|
+
// §R.2 established that the eleven `CaseState`s were never one machine: `approved`/`denied`/`expired`
|
|
4
|
+
// are **decisions**, `revoked` is what happens to a **commitment**, and the rest are **execution**. One
|
|
5
|
+
// field was answering three questions with three different signers, which is why a case could be
|
|
6
|
+
// `denied` while a commitment stayed outstanding with nowhere to record it.
|
|
7
|
+
//
|
|
8
|
+
// §R.3 names the order this has to happen in: the case flow EMITS decision and commitment records
|
|
9
|
+
// FIRST, and only then can `CaseState` shrink to execution. Deleting the enum before this module
|
|
10
|
+
// existed would have replaced working behaviour with machines nothing writes to — a regression wearing
|
|
11
|
+
// the costume of a cleanup.
|
|
12
|
+
//
|
|
13
|
+
// WHAT THIS MODULE IS NOT. It derives records; it does not move state. Every emission is expressed as a
|
|
14
|
+
// TRANSITION to be applied by the owning machine, never as a state assignment, so the machines keep
|
|
15
|
+
// their role checks — the creditor still discharges, the decider still decides, and persistence does
|
|
16
|
+
// not become a bypass (ADR-0058 §15, and the same rule `createDurableObjectInteractionStore` follows).
|
|
17
|
+
//
|
|
18
|
+
// NONE OF THIS IS AUTHORITY. A `grant` here records that a determination was made. It permits nothing:
|
|
19
|
+
// the authority re-check happens at the moment of acting regardless of what any of these records say
|
|
20
|
+
// (ADR-0041, ADR-0043).
|
|
21
|
+
import { applyCommitmentTransition, applyDecisionTransition } from './interaction-machines.js';
|
|
22
|
+
/**
|
|
23
|
+
* Deterministic ids, derived from the case id.
|
|
24
|
+
*
|
|
25
|
+
* Deliberately not random and not clock-derived: a case transition may be replayed (the interaction
|
|
26
|
+
* store is idempotent on `idempotencyKey`, and `processDue` re-runs sweeps), and a fresh id per replay
|
|
27
|
+
* would fork one determination into several. Same case ⇒ same decision ⇒ the second application is a
|
|
28
|
+
* no-op against a terminal state rather than a duplicate record.
|
|
29
|
+
*/
|
|
30
|
+
export function decisionIdForCase(caseId) {
|
|
31
|
+
return `dec_${caseId}`;
|
|
32
|
+
}
|
|
33
|
+
export function commitmentIdForCase(caseId) {
|
|
34
|
+
return `cmt_${caseId}`;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* WHO IS THE CREDITOR. The approving side — `responder` / `resource-owner`.
|
|
38
|
+
*
|
|
39
|
+
* This is a derivation, not a preference. Case `revoke` is signed by `responder`/`resource-owner`, and
|
|
40
|
+
* the only creditor-only commitment transition is `void`. Under the opposite assignment (debtor =
|
|
41
|
+
* responder, creditor = requester) an issuer revoking what it granted has no legal transition at all,
|
|
42
|
+
* which contradicts a case machine that plainly permits it. One reading is self-consistent; the other
|
|
43
|
+
* is not. `issue-credential` corroborates it: its signers are `resource-owner`/`responder` and
|
|
44
|
+
* `activate` is likewise creditor-only.
|
|
45
|
+
*/
|
|
46
|
+
function creditorOf(c) {
|
|
47
|
+
return c.resourceOwner ?? c.responder;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* WHO IS THE DECIDER — and why it is not one rule.
|
|
51
|
+
*
|
|
52
|
+
* For `approve`/`deny` it is `event.actor`: the party that actually made the determination. It cannot
|
|
53
|
+
* be the deciding ROLE, because the case machine accepts EITHER `responder` or `resource-owner` for
|
|
54
|
+
* those moves while the decision machine requires exactly `decision.decider`. Pinning the decider to
|
|
55
|
+
* the role would make a responder-signed approval on a case that also has a resource-owner emit a
|
|
56
|
+
* decision the decision machine then rejects as `unauthorized-actor` — a case that succeeded and an
|
|
57
|
+
* emission that silently could not land.
|
|
58
|
+
*
|
|
59
|
+
* For `expire` it is the creditor. `expire` is signed by role `any` (time is not an actor, so a
|
|
60
|
+
* deterministic sweep may record it), and attributing an expiry to whichever party happened to run the
|
|
61
|
+
* sweep would put a determination in someone's name they never made. The decision machine skips the
|
|
62
|
+
* actor check for `expire` precisely so this is possible.
|
|
63
|
+
*/
|
|
64
|
+
function decisionSeed(c, event, transition) {
|
|
65
|
+
return {
|
|
66
|
+
decisionId: decisionIdForCase(c.id),
|
|
67
|
+
decider: transition === 'expire' ? creditorOf(c) : event.actor,
|
|
68
|
+
subject: c.id,
|
|
69
|
+
expiresAt: c.expiresAt,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
function commitmentSeed(c) {
|
|
73
|
+
return {
|
|
74
|
+
commitmentId: commitmentIdForCase(c.id),
|
|
75
|
+
debtor: c.requester,
|
|
76
|
+
creditor: creditorOf(c),
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* The mapping, stated once.
|
|
81
|
+
*
|
|
82
|
+
* `deliver-credential` is deliberately ABSENT. It completes the case, and completing the work does not
|
|
83
|
+
* discharge the obligation — that is exactly the collapse ADR-0058 §15 forbids, and `fabric` already
|
|
84
|
+
* refuses to draw that edge implicitly (`mayDischargeOnExecution` exists so a profile has to choose it
|
|
85
|
+
* in a diff). A creditor who wants to discharge does so as its own act, against the commitment
|
|
86
|
+
* machine, with its own signature.
|
|
87
|
+
*
|
|
88
|
+
* `fail` is absent for the same reason in the other direction: a failed execution is not a refusal by
|
|
89
|
+
* anyone, and recording it as one would attribute a determination nobody made.
|
|
90
|
+
*/
|
|
91
|
+
const EMITTING_TRANSITIONS = {
|
|
92
|
+
approve: { decision: 'grant' },
|
|
93
|
+
deny: { decision: 'refuse' },
|
|
94
|
+
expire: { decision: 'expire' },
|
|
95
|
+
// Issuing is what creates the obligation, so this emission may bring the commitment into being.
|
|
96
|
+
'issue-credential': { commitment: 'activate' },
|
|
97
|
+
revoke: { commitment: 'void' },
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* Whether an emission may bring its record into existence.
|
|
101
|
+
*
|
|
102
|
+
* Deciding CREATES a determination — there was no prior record and the act of approving or denying is
|
|
103
|
+
* what makes one. Issuing likewise creates the obligation.
|
|
104
|
+
*
|
|
105
|
+
* `void` must not. `revoke` is legal from any non-terminal case, including `submitted`, where nothing
|
|
106
|
+
* was ever approved and no obligation ever arose. Seeding a commitment there so it could immediately
|
|
107
|
+
* be voided would write a record asserting an obligation existed and was released, when neither
|
|
108
|
+
* happened — inventing history to satisfy a type. Absent a commitment, this emission is a no-op, and
|
|
109
|
+
* the case's own `revoked` state remains the honest record of what occurred.
|
|
110
|
+
*/
|
|
111
|
+
const CREATES_ITS_RECORD = {
|
|
112
|
+
grant: true,
|
|
113
|
+
refuse: true,
|
|
114
|
+
expire: true,
|
|
115
|
+
activate: true,
|
|
116
|
+
withdraw: false,
|
|
117
|
+
supersede: false,
|
|
118
|
+
'claim-fulfilment': false,
|
|
119
|
+
'dispute-claim': false,
|
|
120
|
+
discharge: false,
|
|
121
|
+
'assert-breach': false,
|
|
122
|
+
void: false,
|
|
123
|
+
};
|
|
124
|
+
/**
|
|
125
|
+
* Derive what a case transition emits. Pure, and total over `CaseTransition` — a transition with no
|
|
126
|
+
* emission returns `{}` rather than throwing, because most transitions genuinely emit nothing.
|
|
127
|
+
*
|
|
128
|
+
* Call this only for a transition the case machine ACCEPTED. It does not re-check legality: duplicating
|
|
129
|
+
* the case machine's role and ordering rules here would create a second, quietly diverging copy of them.
|
|
130
|
+
*/
|
|
131
|
+
export function caseTransitionEmissions(current, event) {
|
|
132
|
+
const spec = EMITTING_TRANSITIONS[event.transition];
|
|
133
|
+
if (!spec)
|
|
134
|
+
return {};
|
|
135
|
+
const out = {};
|
|
136
|
+
if (spec.decision) {
|
|
137
|
+
out.decision = {
|
|
138
|
+
seed: decisionSeed(current, event, spec.decision),
|
|
139
|
+
transition: spec.decision,
|
|
140
|
+
createIfAbsent: CREATES_ITS_RECORD[spec.decision],
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
if (spec.commitment) {
|
|
144
|
+
out.commitment = {
|
|
145
|
+
seed: commitmentSeed(current),
|
|
146
|
+
transition: spec.commitment,
|
|
147
|
+
createIfAbsent: CREATES_ITS_RECORD[spec.commitment],
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
return out;
|
|
151
|
+
}
|
|
152
|
+
/** The case transitions that emit something. Exported so a test can assert the set rather than
|
|
153
|
+
* restate it, and so a newly-added emitting transition shows up in a diff of this constant. */
|
|
154
|
+
export const EMITTING_CASE_TRANSITIONS = Object.keys(EMITTING_TRANSITIONS);
|
|
155
|
+
/** Seed a decision record in its INITIAL state. Never the resulting state — see `DecisionSeedV1`. */
|
|
156
|
+
export function seedDecision(seed, at) {
|
|
157
|
+
return {
|
|
158
|
+
decisionId: seed.decisionId,
|
|
159
|
+
state: 'pending',
|
|
160
|
+
decider: seed.decider,
|
|
161
|
+
subject: seed.subject,
|
|
162
|
+
expiresAt: seed.expiresAt,
|
|
163
|
+
updatedAt: at,
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
/** Seed a commitment record in its INITIAL state. */
|
|
167
|
+
export function seedCommitment(seed, at) {
|
|
168
|
+
return {
|
|
169
|
+
commitmentId: seed.commitmentId,
|
|
170
|
+
state: 'proposed',
|
|
171
|
+
debtor: seed.debtor,
|
|
172
|
+
creditor: seed.creditor,
|
|
173
|
+
updatedAt: at,
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
function applyOne(emission, existing, create, apply) {
|
|
177
|
+
if (!emission)
|
|
178
|
+
return undefined;
|
|
179
|
+
const record = existing ?? (emission.createIfAbsent ? create() : null);
|
|
180
|
+
if (record === null)
|
|
181
|
+
return { applied: false, reason: 'absent' };
|
|
182
|
+
const res = apply(record, emission.transition);
|
|
183
|
+
return res.ok ? { applied: true, record: res.next } : { applied: false, reason: res.reason };
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Apply emissions through the OWNING machines.
|
|
187
|
+
*
|
|
188
|
+
* The point of this function is what it does not do: it never assigns a state. A record is created
|
|
189
|
+
* only in its initial state and every move goes through `applyDecisionTransition` /
|
|
190
|
+
* `applyCommitmentTransition`, so their role and ordering checks still hold — the creditor still
|
|
191
|
+
* voids, the decider still decides.
|
|
192
|
+
*
|
|
193
|
+
* Rejections are RETURNED, not thrown and not swallowed. A caller that persists these must treat a
|
|
194
|
+
* rejected emission as a fact about the record it failed to write, because a silent no-op here is
|
|
195
|
+
* indistinguishable from success and would leave a case whose determination was never recorded
|
|
196
|
+
* looking exactly like one whose determination was.
|
|
197
|
+
*/
|
|
198
|
+
export function applyCaseEmissions(emissions, existing, event) {
|
|
199
|
+
const out = {};
|
|
200
|
+
const decision = applyOne(emissions.decision, existing.decision, () => seedDecision(emissions.decision.seed, event.at), (record, transition) => applyDecisionTransition(record, { transition, actor: event.actor, at: event.at }));
|
|
201
|
+
if (decision)
|
|
202
|
+
out.decision = decision;
|
|
203
|
+
const commitment = applyOne(emissions.commitment, existing.commitment, () => seedCommitment(emissions.commitment.seed, event.at), (record, transition) => applyCommitmentTransition(record, { transition, actor: event.actor, at: event.at }));
|
|
204
|
+
if (commitment)
|
|
205
|
+
out.commitment = commitment;
|
|
206
|
+
return out;
|
|
207
|
+
}
|
|
208
|
+
//# sourceMappingURL=case-emissions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"case-emissions.js","sourceRoot":"","sources":["../src/case-emissions.ts"],"names":[],"mappings":"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"}
|
package/dist/case-machine.d.ts
CHANGED
|
@@ -52,9 +52,19 @@ export interface CaseTransitionEventV1 {
|
|
|
52
52
|
authorityRef?: AuthorityRef;
|
|
53
53
|
signature?: SignatureProof;
|
|
54
54
|
}
|
|
55
|
+
/** W10b-3: `denied`/`expired`/`revoked` collapsed into `closed` — same terminality, and the verdict
|
|
56
|
+
* that distinguished them now lives in the decision and commitment records. */
|
|
55
57
|
export declare const TERMINAL_CASE_STATES: readonly CaseState[];
|
|
56
58
|
export declare function isTerminalCaseState(state: CaseState): boolean;
|
|
57
|
-
|
|
59
|
+
/** The transitions that cannot land on the case machine alone. Exported so the set is a constant a
|
|
60
|
+
* caller can read rather than a rule buried in a branch. */
|
|
61
|
+
export declare const TRANSITIONS_REQUIRING_GRANTED_DECISION: readonly CaseTransition[];
|
|
62
|
+
export declare function requiresGrantedDecision(transition: CaseTransition): boolean;
|
|
63
|
+
export type CaseRejection = 'wrong-case' | 'invalid-transition' | 'unauthorized-actor' | 'case-expired' | 'not-yet-due'
|
|
64
|
+
/** W10b-3: the transition needs a granted decision and none was supplied. Its own reason rather than
|
|
65
|
+
* `invalid-transition`, because the case IS in a legal state — what is missing is the determination,
|
|
66
|
+
* and a caller that cannot tell those apart will "fix" the wrong one. */
|
|
67
|
+
| 'requires-granted-decision';
|
|
58
68
|
export type CaseResult = {
|
|
59
69
|
ok: true;
|
|
60
70
|
case: FabricCaseV1;
|
|
@@ -62,11 +72,27 @@ export type CaseResult = {
|
|
|
62
72
|
ok: false;
|
|
63
73
|
reason: CaseRejection;
|
|
64
74
|
};
|
|
75
|
+
/**
|
|
76
|
+
* What this machine cannot know on its own (spec 340 W10b-3).
|
|
77
|
+
*
|
|
78
|
+
* Until W10b-3, "you cannot issue before approving" was an FSM edge: `issue-credential` ran only
|
|
79
|
+
* `from: ['approved']`. With the determination moved to the decision machine, `triaged` is reachable by
|
|
80
|
+
* plain triage, so that ordering has to be re-established as a precondition or issuance could skip the
|
|
81
|
+
* determination entirely.
|
|
82
|
+
*
|
|
83
|
+
* Passed IN rather than looked up: this module is pure and has no store. The caller that holds the
|
|
84
|
+
* decision supplies it, and supplying nothing is a refusal, not a pass — a machine that treated
|
|
85
|
+
* "no decision provided" as "no decision required" would be exactly the fail-open this repo forbids.
|
|
86
|
+
*/
|
|
87
|
+
export interface CaseTransitionContext {
|
|
88
|
+
/** The state of the decision for this case, or `null`/absent when there is none. */
|
|
89
|
+
decisionState?: 'pending' | 'granted' | 'refused' | 'withdrawn' | 'expired' | 'superseded' | null;
|
|
90
|
+
}
|
|
65
91
|
/**
|
|
66
92
|
* Pure, fail-closed (spec 316 §2). Generic over the concrete case type: preserves whatever extra fields
|
|
67
93
|
* `T` carries beyond `CaseFsmFields`. Returns the next case or a typed rejection — never a silent no-op.
|
|
68
94
|
*/
|
|
69
|
-
export declare function applyCaseTransition<T extends CaseFsmFields>(current: T, event: CaseTransitionEventV1): {
|
|
95
|
+
export declare function applyCaseTransition<T extends CaseFsmFields>(current: T, event: CaseTransitionEventV1, ctx?: CaseTransitionContext): {
|
|
70
96
|
ok: true;
|
|
71
97
|
case: T;
|
|
72
98
|
} | {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"case-machine.d.ts","sourceRoot":"","sources":["../src/case-machine.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC7E,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACpF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAEvD;uEACuE;AACvE,MAAM,WAAW,aAAa;IAC5B;;4DAEwD;IACxD,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,SAAS,CAAC;IACjB,SAAS,EAAE,gBAAgB,CAAC;IAC5B,SAAS,EAAE,gBAAgB,CAAC;IAC5B,aAAa,CAAC,EAAE,gBAAgB,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,SAAS,CAAC;IAC5B,YAAY,EAAE,QAAQ,EAAE,CAAC;IACzB,aAAa,EAAE,YAAY,EAAE,CAAC;CAC/B;AAED,0GAA0G;AAC1G,MAAM,WAAW,YAAa,SAAQ,aAAa;IACjD,OAAO,EAAE,YAAY,CAAC;IACtB,6DAA6D;IAC7D,EAAE,EAAE,UAAU,CAAC;IACf,IAAI,EAAE,eAAe,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,4EAA4E;IAC5E,WAAW,CAAC,EAAE,YAAY,EAAE,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,SAAS,CAAC;IACzB,eAAe,EAAE,SAAS,CAAC;CAC5B;AAED,8GAA8G;AAC9G,MAAM,MAAM,cAAc,GACtB,QAAQ,GACR,QAAQ,GACR,UAAU,GACV,aAAa,GACb,SAAS,GACT,kBAAkB,GAClB,oBAAoB,GACpB,MAAM,GACN,QAAQ,GACR,QAAQ,GACR,MAAM,CAAC;AAEX,yGAAyG;AACzG,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,kBAAkB,CAAC;IAC5B,+DAA+D;IAC/D,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,cAAc,CAAC;IAC3B,KAAK,EAAE,gBAAgB,CAAC;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,6DAA6D;IAC7D,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,QAAQ,CAAC;IACvB,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,SAAS,CAAC,EAAE,cAAc,CAAC;CAC5B;AAED,eAAO,MAAM,oBAAoB,EAAE,SAAS,SAAS,
|
|
1
|
+
{"version":3,"file":"case-machine.d.ts","sourceRoot":"","sources":["../src/case-machine.ts"],"names":[],"mappings":"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"}
|
package/dist/case-machine.js
CHANGED
|
@@ -14,10 +14,24 @@
|
|
|
14
14
|
// are inbox read-receipt facts. So `admit`(submitted→delivered)/`view`(delivered→seen) are DROPPED (they
|
|
15
15
|
// become `ExchangeEventV1` `kind:'message'` events), and the moves that referenced `seen`/`delivered`
|
|
16
16
|
// re-anchor on `submitted`/`triaged`.
|
|
17
|
-
|
|
17
|
+
/** W10b-3: `denied`/`expired`/`revoked` collapsed into `closed` — same terminality, and the verdict
|
|
18
|
+
* that distinguished them now lives in the decision and commitment records. */
|
|
19
|
+
export const TERMINAL_CASE_STATES = ['completed', 'closed', 'failed'];
|
|
18
20
|
export function isTerminalCaseState(state) {
|
|
19
21
|
return TERMINAL_CASE_STATES.includes(state);
|
|
20
22
|
}
|
|
23
|
+
/**
|
|
24
|
+
* spec 340 W10b-3. The VERBS are unchanged — that is deliberate and load-bearing. A stored v1 case-event
|
|
25
|
+
* log names transitions, not states, so keeping every verb is what lets history replay with no
|
|
26
|
+
* migration (W10b-1). What changed is where four of them LAND, because `approved`/`denied`/`expired`/
|
|
27
|
+
* `revoked` were never execution states (§R.2):
|
|
28
|
+
*
|
|
29
|
+
* · `approve` now lands on `triaged` — the responder is working toward issuance. The DETERMINATION
|
|
30
|
+
* goes to the decision machine via `caseTransitionEmissions`. "Approved" was never a description
|
|
31
|
+
* of how far the work got; reading it as one is the "deciding is not doing" collapse.
|
|
32
|
+
* · `deny`/`expire`/`revoke` land on `closed` — taken up, ended without issuance. The verdict is in
|
|
33
|
+
* the decision record; the voided obligation is in the commitment record.
|
|
34
|
+
*/
|
|
21
35
|
const TRANSITIONS = {
|
|
22
36
|
submit: { from: ['draft'], to: 'submitted', signers: ['requester'] },
|
|
23
37
|
triage: { from: ['submitted'], to: 'triaged', signers: ['responder'] },
|
|
@@ -25,14 +39,24 @@ const TRANSITIONS = {
|
|
|
25
39
|
// needs-info → triaged (NOT submitted): the requester supplied info, the responder RESUMES working
|
|
26
40
|
// (couples to exec `working`), preserving the "responder engaged" phase across the info loop.
|
|
27
41
|
'submit-info': { from: ['needs-info'], to: 'triaged', signers: ['requester'] },
|
|
28
|
-
approve: { from: ['submitted', 'triaged'], to: '
|
|
29
|
-
|
|
42
|
+
approve: { from: ['submitted', 'triaged'], to: 'triaged', signers: ['responder', 'resource-owner'] },
|
|
43
|
+
// `from: ['triaged']` plus a REQUIRED granted decision — see `requiresGrantedDecision`. The ordering
|
|
44
|
+
// "you cannot issue before approving" used to be an FSM edge (`from: ['approved']`); with the
|
|
45
|
+
// decision out of this enum it becomes a cross-machine precondition instead, because `triaged` is
|
|
46
|
+
// reachable by plain triage and would otherwise let issuance skip the determination entirely.
|
|
47
|
+
'issue-credential': { from: ['triaged'], to: 'issued', signers: ['resource-owner', 'responder'] },
|
|
30
48
|
'deliver-credential': { from: ['issued'], to: 'completed', signers: ['resource-owner', 'responder'] },
|
|
31
|
-
deny: { from: 'any-non-terminal', to: '
|
|
32
|
-
expire: { from: 'any-non-terminal', to: '
|
|
33
|
-
revoke: { from: 'any-non-terminal', to: '
|
|
49
|
+
deny: { from: 'any-non-terminal', to: 'closed', signers: ['responder', 'resource-owner'] },
|
|
50
|
+
expire: { from: 'any-non-terminal', to: 'closed', signers: ['any'] },
|
|
51
|
+
revoke: { from: 'any-non-terminal', to: 'closed', signers: ['responder', 'resource-owner'] },
|
|
34
52
|
fail: { from: 'any-non-terminal', to: 'failed', signers: ['any'] },
|
|
35
53
|
};
|
|
54
|
+
/** The transitions that cannot land on the case machine alone. Exported so the set is a constant a
|
|
55
|
+
* caller can read rather than a rule buried in a branch. */
|
|
56
|
+
export const TRANSITIONS_REQUIRING_GRANTED_DECISION = ['issue-credential'];
|
|
57
|
+
export function requiresGrantedDecision(transition) {
|
|
58
|
+
return TRANSITIONS_REQUIRING_GRANTED_DECISION.includes(transition);
|
|
59
|
+
}
|
|
36
60
|
function actorRoles(c, actor) {
|
|
37
61
|
const roles = new Set(['any']);
|
|
38
62
|
if (actor === c.requester)
|
|
@@ -50,7 +74,7 @@ function isPastExpiry(c, atIso) {
|
|
|
50
74
|
* Pure, fail-closed (spec 316 §2). Generic over the concrete case type: preserves whatever extra fields
|
|
51
75
|
* `T` carries beyond `CaseFsmFields`. Returns the next case or a typed rejection — never a silent no-op.
|
|
52
76
|
*/
|
|
53
|
-
export function applyCaseTransition(current, event) {
|
|
77
|
+
export function applyCaseTransition(current, event, ctx = {}) {
|
|
54
78
|
if (event.caseId !== current.id)
|
|
55
79
|
return { ok: false, reason: 'wrong-case' };
|
|
56
80
|
const spec = TRANSITIONS[event.transition];
|
|
@@ -59,6 +83,9 @@ export function applyCaseTransition(current, event) {
|
|
|
59
83
|
const fromOk = spec.from === 'any-non-terminal' ? !isTerminalCaseState(current.state) : spec.from.includes(current.state);
|
|
60
84
|
if (!fromOk)
|
|
61
85
|
return { ok: false, reason: 'invalid-transition' };
|
|
86
|
+
if (requiresGrantedDecision(event.transition) && ctx.decisionState !== 'granted') {
|
|
87
|
+
return { ok: false, reason: 'requires-granted-decision' };
|
|
88
|
+
}
|
|
62
89
|
// `expire` only lands once the deadline passed; everything else (except `fail`) rejects on an expired case.
|
|
63
90
|
if (event.transition === 'expire') {
|
|
64
91
|
if (current.expiresAt === undefined || !isPastExpiry(current, event.at))
|
package/dist/case-machine.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"case-machine.js","sourceRoot":"","sources":["../src/case-machine.ts"],"names":[],"mappings":"AAAA,yGAAyG;AACzG,wGAAwG;AACxG,kCAAkC;AAClC,+GAA+G;AAC/G,4EAA4E;AAC5E,sGAAsG;AACtG,8BAA8B;AAC9B,EAAE;AACF,4GAA4G;AAC5G,6GAA6G;AAC7G,2FAA2F;AAC3F,EAAE;AACF,2GAA2G;AAC3G,yGAAyG;AACzG,sGAAsG;AACtG,sCAAsC;AAwEtC,MAAM,CAAC,MAAM,oBAAoB,GAAyB,CAAC,
|
|
1
|
+
{"version":3,"file":"case-machine.js","sourceRoot":"","sources":["../src/case-machine.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { createDurableObjectSqlVault } from './sql-vault.js';
|
|
2
2
|
export { createDurableObjectExchangeStore, type ExchangeStore } from './exchange-store.js';
|
|
3
|
+
export { createDurableObjectInteractionStore, type InteractionStore, type SnapshotPutResult, } from './interaction-store.js';
|
|
3
4
|
export { createDurableObjectOutboxStore, type OutboxStore, type OutboxEntry } from './outbox-store.js';
|
|
4
5
|
export { createDurableObjectProvenanceStore, type ProvenanceStore } from './provenance-store.js';
|
|
5
6
|
export { createDurableObjectChannelStore, projectionAuthorizes, type ChannelStore, type ChannelV1, type ConversationRoleProjection, type ConversationRoleAction, } from './channel-store.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cloudflare/index.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,2BAA2B,EAAE,MAAM,gBAAgB,CAAC;AAC7D,OAAO,EAAE,gCAAgC,EAAE,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cloudflare/index.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,2BAA2B,EAAE,MAAM,gBAAgB,CAAC;AAC7D,OAAO,EAAE,gCAAgC,EAAE,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAI3F,OAAO,EACL,mCAAmC,EACnC,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,GACvB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,8BAA8B,EAAE,KAAK,WAAW,EAAE,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACvG,OAAO,EAAE,kCAAkC,EAAE,KAAK,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACjG,OAAO,EACL,+BAA+B,EAAE,oBAAoB,EACrD,KAAK,YAAY,EAAE,KAAK,SAAS,EAAE,KAAK,0BAA0B,EAAE,KAAK,sBAAsB,GAChG,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,wCAAwC,EACxC,KAAK,qBAAqB,EAC1B,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,GACzB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,kCAAkC,EAAE,KAAK,eAAe,EAAE,KAAK,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC7H,OAAO,EACL,gCAAgC,EAChC,qBAAqB,EACrB,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EACzB,KAAK,uBAAuB,GAC7B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,kBAAkB,EAAE,KAAK,mBAAmB,EAAE,KAAK,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAC3G,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,KAAK,WAAW,EAChB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,GACzB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AAE/G,eAAO,MAAM,gCAAgC,EAAG,mBAA4B,CAAC"}
|
package/dist/cloudflare/index.js
CHANGED
|
@@ -7,6 +7,10 @@
|
|
|
7
7
|
// absorption follow in subsequent W2 steps.
|
|
8
8
|
export { createDurableObjectSqlVault } from './sql-vault.js';
|
|
9
9
|
export { createDurableObjectExchangeStore } from './exchange-store.js';
|
|
10
|
+
// The interaction spine's durable home (spec 340 W6) — interactions, context snapshots, decisions,
|
|
11
|
+
// commitments and per-viewer inbox state. Five tables, because the six machines answer to different
|
|
12
|
+
// parties at different times and one row would make them one write.
|
|
13
|
+
export { createDurableObjectInteractionStore, } from './interaction-store.js';
|
|
10
14
|
export { createDurableObjectOutboxStore } from './outbox-store.js';
|
|
11
15
|
export { createDurableObjectProvenanceStore } from './provenance-store.js';
|
|
12
16
|
export { createDurableObjectChannelStore, projectionAuthorizes, } from './channel-store.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cloudflare/index.ts"],"names":[],"mappings":"AAAA,0GAA0G;AAC1G,EAAE;AACF,wGAAwG;AACxG,wGAAwG;AACxG,yGAAyG;AACzG,yGAAyG;AACzG,4CAA4C;AAC5C,OAAO,EAAE,2BAA2B,EAAE,MAAM,gBAAgB,CAAC;AAC7D,OAAO,EAAE,gCAAgC,EAAsB,MAAM,qBAAqB,CAAC;AAC3F,OAAO,EAAE,8BAA8B,EAAsC,MAAM,mBAAmB,CAAC;AACvG,OAAO,EAAE,kCAAkC,EAAwB,MAAM,uBAAuB,CAAC;AACjG,OAAO,EACL,+BAA+B,EAAE,oBAAoB,GAEtD,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,wCAAwC,GAIzC,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,kCAAkC,EAAmD,MAAM,wBAAwB,CAAC;AAC7H,OAAO,EACL,gCAAgC,EAChC,qBAAqB,GAItB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,kBAAkB,EAA8C,MAAM,2BAA2B,CAAC;AAC3G,OAAO,EACL,eAAe,EACf,kBAAkB,GAInB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AAE/G,MAAM,CAAC,MAAM,gCAAgC,GAAG,mBAA4B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cloudflare/index.ts"],"names":[],"mappings":"AAAA,0GAA0G;AAC1G,EAAE;AACF,wGAAwG;AACxG,wGAAwG;AACxG,yGAAyG;AACzG,yGAAyG;AACzG,4CAA4C;AAC5C,OAAO,EAAE,2BAA2B,EAAE,MAAM,gBAAgB,CAAC;AAC7D,OAAO,EAAE,gCAAgC,EAAsB,MAAM,qBAAqB,CAAC;AAC3F,mGAAmG;AACnG,oGAAoG;AACpG,oEAAoE;AACpE,OAAO,EACL,mCAAmC,GAGpC,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,8BAA8B,EAAsC,MAAM,mBAAmB,CAAC;AACvG,OAAO,EAAE,kCAAkC,EAAwB,MAAM,uBAAuB,CAAC;AACjG,OAAO,EACL,+BAA+B,EAAE,oBAAoB,GAEtD,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,wCAAwC,GAIzC,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,kCAAkC,EAAmD,MAAM,wBAAwB,CAAC;AAC7H,OAAO,EACL,gCAAgC,EAChC,qBAAqB,GAItB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,kBAAkB,EAA8C,MAAM,2BAA2B,CAAC;AAC3G,OAAO,EACL,eAAe,EACf,kBAAkB,GAInB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AAE/G,MAAM,CAAC,MAAM,gCAAgC,GAAG,mBAA4B,CAAC"}
|