@helmetfire-labs/cartridge-common 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +206 -0
- package/dist/action-schema.d.ts +71 -0
- package/dist/action-schema.js +94 -0
- package/dist/action-schema.js.map +1 -0
- package/dist/actions.d.ts +4 -0
- package/dist/actions.js +5 -0
- package/dist/actions.js.map +1 -1
- package/dist/container-reducer.d.ts +104 -0
- package/dist/container-reducer.js +178 -0
- package/dist/container-reducer.js.map +1 -0
- package/dist/durable-dispatcher.d.ts +90 -0
- package/dist/durable-dispatcher.js +198 -0
- package/dist/durable-dispatcher.js.map +1 -0
- package/dist/durable-reducer.d.ts +108 -0
- package/dist/durable-reducer.js +40 -0
- package/dist/durable-reducer.js.map +1 -0
- package/dist/index.d.ts +25 -2
- package/dist/index.js +21 -2
- package/dist/index.js.map +1 -1
- package/dist/logger.d.ts +10 -3
- package/dist/logger.js +24 -1
- package/dist/logger.js.map +1 -1
- package/dist/namespace.d.ts +99 -0
- package/dist/namespace.js +161 -0
- package/dist/namespace.js.map +1 -0
- package/dist/policy.d.ts +118 -0
- package/dist/policy.js +204 -0
- package/dist/policy.js.map +1 -0
- package/dist/tags.d.ts +3 -0
- package/dist/tags.js +3 -0
- package/dist/tags.js.map +1 -1
- package/dist/trace.d.ts +57 -0
- package/dist/trace.js +57 -0
- package/dist/trace.js.map +1 -1
- package/dist/trust-score.d.ts +132 -0
- package/dist/trust-score.js +233 -0
- package/dist/trust-score.js.map +1 -0
- package/dist/trust-tiers.d.ts +68 -0
- package/dist/trust-tiers.js +264 -0
- package/dist/trust-tiers.js.map +1 -0
- package/dist/verify.d.ts +36 -0
- package/dist/verify.js +110 -0
- package/dist/verify.js.map +1 -0
- package/package.json +10 -6
package/README.md
ADDED
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
# @helmetfire-labs/cartridge-common
|
|
2
|
+
|
|
3
|
+
Shared logging, error boundaries, trace helpers, durable reducer runtime, and trust infrastructure for AgentRuntime cartridges.
|
|
4
|
+
|
|
5
|
+
This is a **library**, not a service. It provides the building blocks that all cartridges use for structured logging, error handling, multi-agent state isolation, and auditable state management.
|
|
6
|
+
|
|
7
|
+
## Philosophy
|
|
8
|
+
|
|
9
|
+
Every cartridge is a process with a behavioral contract. It declares what it does (action schema), what it's allowed to do (process policy), and how its state changes over time (reducer). All three are cryptographically bound — the action log is hash-chained, the policy is signed at write time, and the verifier can replay any cartridge's history to prove correctness.
|
|
10
|
+
|
|
11
|
+
Infrastructure cartridges never expose admin APIs. The operator reads logs and edits config — the Conversational Control Plane. Trust is earned through observable behavior: verified action logs, policy compliance, and operator attestation feed a scoring engine that automates tier promotion from T0 (untrusted) through T5 (community-verified).
|
|
12
|
+
|
|
13
|
+
## Install
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install @helmetfire-labs/cartridge-common
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Exports
|
|
20
|
+
|
|
21
|
+
### Logging & Observability
|
|
22
|
+
|
|
23
|
+
| Export | Module | Description |
|
|
24
|
+
|--------|--------|-------------|
|
|
25
|
+
| `logEvent`, `LogEventOpts` | `logger` | Structured log event emitter |
|
|
26
|
+
| `TAGS`, `isValidTag`, `TagKey`, `TagValue` | `tags` | Standard tag constants and validation |
|
|
27
|
+
| `ACTIONS`, `ActionKey`, `ActionValue` | `actions` | Standard action verb constants |
|
|
28
|
+
| `generateTraceId`, `extractTraceId`, `traceMetadata`, `extractHop`, `NO_TRACE` | `trace` | Trace ID generation and propagation |
|
|
29
|
+
| `extractShape` | `shape` | Error shape extraction |
|
|
30
|
+
| `withErrorBoundary`, `classifyError`, `ERROR_SHAPES`, `ErrorShapeKey` | `errors` | Error boundary wrapper and classification |
|
|
31
|
+
|
|
32
|
+
### Namespace Scope (Multi-Agent State Isolation)
|
|
33
|
+
|
|
34
|
+
| Export | Module | Description |
|
|
35
|
+
|--------|--------|-------------|
|
|
36
|
+
| `extractNamespace`, `ScopedStateManager` | `namespace` | Multi-agent namespace isolation |
|
|
37
|
+
| `ScopeMode`, `CrossNamespacePolicy`, `NamespaceScopeConfig`, `NamespaceInfo` | `namespace` | Namespace type definitions |
|
|
38
|
+
|
|
39
|
+
### Durable Reducer Runtime
|
|
40
|
+
|
|
41
|
+
| Export | Module | Description |
|
|
42
|
+
|--------|--------|-------------|
|
|
43
|
+
| `sha256`, `hashState`, `hashLine` | `durable-reducer` | Cryptographic hashing for state and action logs |
|
|
44
|
+
| `DurableReducer`, `DurableActionLogEntry`, `VerifyResult`, `VerifyFailure` | `durable-reducer` | Reducer types and verification result types |
|
|
45
|
+
| `DurableDispatcher`, `DispatcherConfig` | `durable-dispatcher` | Persistent dispatcher with hash-chained action logging |
|
|
46
|
+
| `verify` | `verify` | Replay-based action log verification |
|
|
47
|
+
| `containerReducer`, `containerActionSchema`, `ContainerStatus`, `ContainerState`, `ContainerAction` | `container-reducer` | Built-in reducer for container lifecycle |
|
|
48
|
+
|
|
49
|
+
### Action Schemas
|
|
50
|
+
|
|
51
|
+
| Export | Module | Description |
|
|
52
|
+
|--------|--------|-------------|
|
|
53
|
+
| `defineActionSchema`, `action`, `writeActionSchema`, `getSchemaHash`, `validateAction` | `action-schema` | Schema definition, validation, and persistence |
|
|
54
|
+
| `ActionSchema`, `ActionVariant`, `FieldType` | `action-schema` | Schema type definitions |
|
|
55
|
+
|
|
56
|
+
### Process Policy
|
|
57
|
+
|
|
58
|
+
| Export | Module | Description |
|
|
59
|
+
|--------|--------|-------------|
|
|
60
|
+
| `hashPolicy`, `writePolicy`, `readPolicy`, `verifyPolicy` | `policy` | Cryptographically-verified process policy lifecycle |
|
|
61
|
+
| `isNetworkAllowed`, `isFilesystemAllowed`, `isSpawnAllowed` | `policy` | Runtime permission checks |
|
|
62
|
+
| `DEFAULT_POLICY`, `INSTALL_POLICY` | `policy` | Standard policy presets |
|
|
63
|
+
| `CartridgePolicy`, `FilesystemPolicy`, `NetworkPolicy`, `NetworkEndpoint`, `ProcessPolicy`, `PolicyVerifyResult` | `policy` | Policy type definitions |
|
|
64
|
+
|
|
65
|
+
### Trust Tiers & Scoring
|
|
66
|
+
|
|
67
|
+
| Export | Module | Description |
|
|
68
|
+
|--------|--------|-------------|
|
|
69
|
+
| `evaluateTrust`, `checkT3`, `checkT4` | `trust-tiers` | Automated trust tier evaluation (T0–T5) |
|
|
70
|
+
| `TrustTier`, `TierCheck`, `TrustAssessment` | `trust-tiers` | Trust tier type definitions |
|
|
71
|
+
| `computeTrustDelta`, `applyDecay`, `updateTrustScore`, `computeTrustBadge`, `badgeLabel` | `trust-score` | T5 consensus trust scoring engine |
|
|
72
|
+
| `countAnchorConsistency`, `recencyWeight`, `getOperatorWeight`, `initialTrustScoreState` | `trust-score` | Scoring utilities and initial state |
|
|
73
|
+
| `OperatorTier`, `TrustBadge`, `TrustSignal`, `TrustScoreState`, `AnchorConsistencyInput` | `trust-score` | Scoring type definitions |
|
|
74
|
+
|
|
75
|
+
## Durable Reducer Runtime
|
|
76
|
+
|
|
77
|
+
The reducer runtime gives every cartridge an auditable, replay-verifiable state machine.
|
|
78
|
+
|
|
79
|
+
```typescript
|
|
80
|
+
import {
|
|
81
|
+
DurableDispatcher,
|
|
82
|
+
containerReducer,
|
|
83
|
+
type ContainerState,
|
|
84
|
+
type ContainerAction,
|
|
85
|
+
} from "@helmetfire-labs/cartridge-common";
|
|
86
|
+
|
|
87
|
+
// Create a dispatcher — persists hash-chained action.log
|
|
88
|
+
const dispatcher = new DurableDispatcher<ContainerState, ContainerAction>({
|
|
89
|
+
reducer: containerReducer,
|
|
90
|
+
configDir: "./config",
|
|
91
|
+
skipProjection: true, // don't write clear.json (incremental integration)
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
// Dispatch typed actions — each entry gets a stateHash binding
|
|
95
|
+
dispatcher.dispatch({ type: "start", name: "registry", pid: 1234, timestamp: Date.now() });
|
|
96
|
+
|
|
97
|
+
// Verify the log — replays all actions and checks hash chain integrity
|
|
98
|
+
import { verify } from "@helmetfire-labs/cartridge-common";
|
|
99
|
+
const result = await verify(containerReducer, "./config/action.log");
|
|
100
|
+
// result.ok === true if the log is tamper-free
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Action Schemas
|
|
104
|
+
|
|
105
|
+
Define typed, validated action schemas for your reducer:
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
import { defineActionSchema, action } from "@helmetfire-labs/cartridge-common";
|
|
109
|
+
|
|
110
|
+
const schema = defineActionSchema("my-cartridge", [
|
|
111
|
+
action("init", { name: "string" }),
|
|
112
|
+
action("update", { value: "number", reason: "string?" }), // ? = optional
|
|
113
|
+
action("reset"),
|
|
114
|
+
]);
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Process Policy
|
|
118
|
+
|
|
119
|
+
Self-declared, cryptographically-verified permissions for cartridge sandboxing:
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
import { writePolicy, verifyPolicy, isNetworkAllowed } from "@helmetfire-labs/cartridge-common";
|
|
123
|
+
|
|
124
|
+
// Write a signed policy to config/
|
|
125
|
+
await writePolicy("./config", {
|
|
126
|
+
filesystem: { read: ["./data/**"], write: ["./state/**"], deny: ["/etc/**"] },
|
|
127
|
+
network: { allow: [{ host: "api.example.com", port: 443 }], denyAll: false },
|
|
128
|
+
process: { allowSpawn: false, allowedCommands: [] },
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
// Verify policy hasn't been tampered with
|
|
132
|
+
const result = await verifyPolicy("./config");
|
|
133
|
+
// result.ok === true
|
|
134
|
+
|
|
135
|
+
// Runtime permission checks
|
|
136
|
+
isNetworkAllowed(policy, "api.example.com", 443); // true
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Namespace Scope (Multi-Agent State Isolation)
|
|
140
|
+
|
|
141
|
+
When multiple agents connect to the same SSE MCP tool server, each agent needs its own isolated state. The supervisor assigns each agent a namespace via `?ns=<name>` on the SSE URL. Agents never control their own namespace — the supervisor asserts the identity.
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
import { extractNamespace, ScopedStateManager } from "@helmetfire-labs/cartridge-common";
|
|
145
|
+
|
|
146
|
+
const state = new ScopedStateManager({
|
|
147
|
+
mode: "isolated", // "isolated" | "shared" | "hybrid"
|
|
148
|
+
crossNamespace: "allow" // "allow" | "log" | "deny"
|
|
149
|
+
}, "brw");
|
|
150
|
+
|
|
151
|
+
const ns = extractNamespace(req.url); // e.g. "claude" from ?ns=claude
|
|
152
|
+
state.registerSession(transport.sessionId, ns);
|
|
153
|
+
const store = state.getStore(transport.sessionId, "view_page");
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Scope Modes
|
|
157
|
+
|
|
158
|
+
| Mode | Behavior |
|
|
159
|
+
|------|----------|
|
|
160
|
+
| `isolated` | Each agent gets its own state partition |
|
|
161
|
+
| `shared` | All agents share one state pool, `ns` tracks attribution |
|
|
162
|
+
| `hybrid` | Some tools isolated, some shared (configured via `sharedTools`) |
|
|
163
|
+
|
|
164
|
+
### Cross-Namespace Policy
|
|
165
|
+
|
|
166
|
+
| Policy | Behavior |
|
|
167
|
+
|--------|----------|
|
|
168
|
+
| `allow` | No enforcement (default, for development) |
|
|
169
|
+
| `log` | Access permitted but logged with attribution |
|
|
170
|
+
| `deny` | Access rejected, escalation requires attributed override |
|
|
171
|
+
|
|
172
|
+
## Standard Tags
|
|
173
|
+
|
|
174
|
+
| Key | Tag | Cartridge |
|
|
175
|
+
|-----|-----|-----------|
|
|
176
|
+
| `mutex` | `mtx` | mcp-mutex |
|
|
177
|
+
| `semaphore` | `sem` | mcp-semaphore |
|
|
178
|
+
| `readonly` | `rdo` | mcp-readonly |
|
|
179
|
+
| `retry` | `rty` | mcp-retry |
|
|
180
|
+
| `timeout` | `tmo` | mcp-timeout |
|
|
181
|
+
| `circuitBreaker` | `brk` | mcp-circuit-breaker |
|
|
182
|
+
| `router` | `rtr` | mcp-router |
|
|
183
|
+
| `cache` | `cch` | mcp-cache |
|
|
184
|
+
| `auth` | `aut` | mcp-auth |
|
|
185
|
+
| `transform` | `tfm` | mcp-transform |
|
|
186
|
+
| `sanitize` | `san` | mcp-sanitize |
|
|
187
|
+
| `webhook` | `whk` | mcp-webhook |
|
|
188
|
+
| `cron` | `crn` | mcp-cron |
|
|
189
|
+
| `audit` | `aud` | mcp-audit |
|
|
190
|
+
| `relay` | `rly` | mcp-relay |
|
|
191
|
+
| `mock` | `mck` | mcp-mock |
|
|
192
|
+
| `shadow` | `shd` | mcp-shadow |
|
|
193
|
+
| `bridge` | `brg` | mcp-bridge |
|
|
194
|
+
| `tee` | `tee` | mcp-tee |
|
|
195
|
+
| `approval` | `apv` | mcp-approval |
|
|
196
|
+
| `verify` | `vfy` | mcp-verify |
|
|
197
|
+
| `browser` | `brw` | tools-browser |
|
|
198
|
+
| `namespace` | `nsp` | namespace scope |
|
|
199
|
+
|
|
200
|
+
## Build
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
npm run build # compile TypeScript
|
|
204
|
+
npm run typecheck # type-check only
|
|
205
|
+
npm test # run tests (239 tests)
|
|
206
|
+
```
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Action schema — runtime-inspectable declaration of a cartridge's action types.
|
|
3
|
+
*
|
|
4
|
+
* TypeScript types are erased at runtime. The action schema bridges this gap:
|
|
5
|
+
* cartridge authors declare their action variants as data (not just types),
|
|
6
|
+
* and the schema generator outputs action-schema.json for the marketplace.
|
|
7
|
+
*
|
|
8
|
+
* The schema serves three purposes:
|
|
9
|
+
* 1. Marketplace declaration — "here are the actions this cartridge can take"
|
|
10
|
+
* 2. Verification input — auditors know what action types to expect
|
|
11
|
+
* 3. Population consensus — the registry compares action distributions
|
|
12
|
+
*
|
|
13
|
+
* Usage:
|
|
14
|
+
* const schema = defineActionSchema("container", [
|
|
15
|
+
* action("start", { ts: "number" }),
|
|
16
|
+
* action("ready", { pid: "number", port: "number?", ts: "number" }),
|
|
17
|
+
* action("stop", { reason: "string", ts: "number" }),
|
|
18
|
+
* // ...
|
|
19
|
+
* ]);
|
|
20
|
+
*
|
|
21
|
+
* writeActionSchema(configDir, schema);
|
|
22
|
+
* // → config/action-schema.json
|
|
23
|
+
*
|
|
24
|
+
* Patent M: Reducer-Based Auditable Cartridge Runtime
|
|
25
|
+
*/
|
|
26
|
+
export type FieldType = "string" | "number" | "boolean" | "string?" | "number?" | "boolean?" | "unknown";
|
|
27
|
+
export interface ActionVariant {
|
|
28
|
+
/** The discriminant value (e.g. "start", "stop", "crash") */
|
|
29
|
+
type: string;
|
|
30
|
+
/** Field name → type. Every variant implicitly has `type: string`. */
|
|
31
|
+
fields: Record<string, FieldType>;
|
|
32
|
+
/** Human-readable description of what this action represents */
|
|
33
|
+
description?: string;
|
|
34
|
+
}
|
|
35
|
+
export interface ActionSchema {
|
|
36
|
+
/** Schema format version */
|
|
37
|
+
version: 1;
|
|
38
|
+
/** Cartridge/reducer name */
|
|
39
|
+
name: string;
|
|
40
|
+
/** All declared action variants */
|
|
41
|
+
actions: ActionVariant[];
|
|
42
|
+
/** SHA-256 of the canonical JSON representation (for identity binding) */
|
|
43
|
+
hash: string;
|
|
44
|
+
/** When this schema was generated */
|
|
45
|
+
generatedAt: number;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Declare a single action variant.
|
|
49
|
+
*/
|
|
50
|
+
export declare function action(type: string, fields: Record<string, FieldType>, description?: string): ActionVariant;
|
|
51
|
+
/**
|
|
52
|
+
* Build a complete action schema from declared variants.
|
|
53
|
+
* Computes the hash over the canonical representation (sorted, no whitespace).
|
|
54
|
+
*/
|
|
55
|
+
export declare function defineActionSchema(name: string, actions: ActionVariant[]): ActionSchema;
|
|
56
|
+
/**
|
|
57
|
+
* Write action-schema.json to the cartridge's config/ directory.
|
|
58
|
+
*/
|
|
59
|
+
export declare function writeActionSchema(configDir: string, schema: ActionSchema): void;
|
|
60
|
+
/**
|
|
61
|
+
* Get just the hash of a schema (for embedding in static.json).
|
|
62
|
+
*/
|
|
63
|
+
export declare function getSchemaHash(schema: ActionSchema): string;
|
|
64
|
+
/**
|
|
65
|
+
* Validate that an action payload conforms to a declared schema.
|
|
66
|
+
* Returns null if valid, or an error string if not.
|
|
67
|
+
*/
|
|
68
|
+
export declare function validateAction(actionPayload: {
|
|
69
|
+
type: string;
|
|
70
|
+
[key: string]: unknown;
|
|
71
|
+
}, schema: ActionSchema): string | null;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Action schema — runtime-inspectable declaration of a cartridge's action types.
|
|
3
|
+
*
|
|
4
|
+
* TypeScript types are erased at runtime. The action schema bridges this gap:
|
|
5
|
+
* cartridge authors declare their action variants as data (not just types),
|
|
6
|
+
* and the schema generator outputs action-schema.json for the marketplace.
|
|
7
|
+
*
|
|
8
|
+
* The schema serves three purposes:
|
|
9
|
+
* 1. Marketplace declaration — "here are the actions this cartridge can take"
|
|
10
|
+
* 2. Verification input — auditors know what action types to expect
|
|
11
|
+
* 3. Population consensus — the registry compares action distributions
|
|
12
|
+
*
|
|
13
|
+
* Usage:
|
|
14
|
+
* const schema = defineActionSchema("container", [
|
|
15
|
+
* action("start", { ts: "number" }),
|
|
16
|
+
* action("ready", { pid: "number", port: "number?", ts: "number" }),
|
|
17
|
+
* action("stop", { reason: "string", ts: "number" }),
|
|
18
|
+
* // ...
|
|
19
|
+
* ]);
|
|
20
|
+
*
|
|
21
|
+
* writeActionSchema(configDir, schema);
|
|
22
|
+
* // → config/action-schema.json
|
|
23
|
+
*
|
|
24
|
+
* Patent M: Reducer-Based Auditable Cartridge Runtime
|
|
25
|
+
*/
|
|
26
|
+
import { writeFileSync } from "node:fs";
|
|
27
|
+
import { resolve } from "node:path";
|
|
28
|
+
import { sha256 } from "./durable-reducer.js";
|
|
29
|
+
// ── Builder ─────────────────────────────────────────────────────────────────
|
|
30
|
+
/**
|
|
31
|
+
* Declare a single action variant.
|
|
32
|
+
*/
|
|
33
|
+
export function action(type, fields, description) {
|
|
34
|
+
return { type, fields, description };
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Build a complete action schema from declared variants.
|
|
38
|
+
* Computes the hash over the canonical representation (sorted, no whitespace).
|
|
39
|
+
*/
|
|
40
|
+
export function defineActionSchema(name, actions) {
|
|
41
|
+
// Sort actions by type for canonical ordering
|
|
42
|
+
const sorted = [...actions].sort((a, b) => a.type.localeCompare(b.type));
|
|
43
|
+
// Canonical representation for hashing (no whitespace, sorted keys)
|
|
44
|
+
const canonical = JSON.stringify({ name, actions: sorted });
|
|
45
|
+
const hash = sha256(canonical);
|
|
46
|
+
return {
|
|
47
|
+
version: 1,
|
|
48
|
+
name,
|
|
49
|
+
actions: sorted,
|
|
50
|
+
hash,
|
|
51
|
+
generatedAt: Date.now(),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
// ── Persistence ─────────────────────────────────────────────────────────────
|
|
55
|
+
/**
|
|
56
|
+
* Write action-schema.json to the cartridge's config/ directory.
|
|
57
|
+
*/
|
|
58
|
+
export function writeActionSchema(configDir, schema) {
|
|
59
|
+
const filePath = resolve(configDir, "action-schema.json");
|
|
60
|
+
writeFileSync(filePath, JSON.stringify(schema, null, 2), "utf-8");
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Get just the hash of a schema (for embedding in static.json).
|
|
64
|
+
*/
|
|
65
|
+
export function getSchemaHash(schema) {
|
|
66
|
+
return schema.hash;
|
|
67
|
+
}
|
|
68
|
+
// ── Validation ──────────────────────────────────────────────────────────────
|
|
69
|
+
/**
|
|
70
|
+
* Validate that an action payload conforms to a declared schema.
|
|
71
|
+
* Returns null if valid, or an error string if not.
|
|
72
|
+
*/
|
|
73
|
+
export function validateAction(actionPayload, schema) {
|
|
74
|
+
const variant = schema.actions.find(a => a.type === actionPayload.type);
|
|
75
|
+
if (!variant) {
|
|
76
|
+
return `unknown action type: "${actionPayload.type}" (declared: ${schema.actions.map(a => a.type).join(", ")})`;
|
|
77
|
+
}
|
|
78
|
+
for (const [field, fieldType] of Object.entries(variant.fields)) {
|
|
79
|
+
const value = actionPayload[field];
|
|
80
|
+
const isOptional = fieldType.endsWith("?");
|
|
81
|
+
const baseType = fieldType.replace("?", "");
|
|
82
|
+
if (value === undefined || value === null) {
|
|
83
|
+
if (!isOptional) {
|
|
84
|
+
return `missing required field "${field}" on action "${actionPayload.type}"`;
|
|
85
|
+
}
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
if (baseType !== "unknown" && typeof value !== baseType) {
|
|
89
|
+
return `field "${field}" on action "${actionPayload.type}": expected ${baseType}, got ${typeof value}`;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=action-schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"action-schema.js","sourceRoot":"","sources":["../src/action-schema.ts"],"names":[],"mappings":"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"}
|
package/dist/actions.d.ts
CHANGED
|
@@ -30,6 +30,10 @@ export declare const ACTIONS: {
|
|
|
30
30
|
readonly pending: "pending";
|
|
31
31
|
readonly approved: "approved";
|
|
32
32
|
readonly rejected: "rejected";
|
|
33
|
+
readonly verify: "verify";
|
|
34
|
+
readonly mismatch: "mismatch";
|
|
35
|
+
readonly signed: "signed";
|
|
36
|
+
readonly anchored: "anchored";
|
|
33
37
|
};
|
|
34
38
|
export type ActionKey = keyof typeof ACTIONS;
|
|
35
39
|
export type ActionValue = (typeof ACTIONS)[ActionKey];
|
package/dist/actions.js
CHANGED
package/dist/actions.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"actions.js","sourceRoot":"","sources":["../src/actions.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG;IACrB,YAAY;IACZ,IAAI,EAAE,MAAM;IACZ,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,SAAS;IAClB,QAAQ,EAAE,UAAU;IACpB,UAAU,EAAE,YAAY;IAExB,UAAU;IACV,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,SAAS;IAClB,MAAM,EAAE,QAAQ;IAEhB,WAAW;IACX,EAAE,EAAE,IAAI;IACR,KAAK,EAAE,OAAO;IACd,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,SAAS;IAElB,QAAQ;IACR,GAAG,EAAE,KAAK;IACV,IAAI,EAAE,MAAM;IACZ,KAAK,EAAE,OAAO;IAEd,kBAAkB;IAClB,IAAI,EAAE,MAAM;IACZ,MAAM,EAAE,QAAQ;IAChB,SAAS,EAAE,WAAW;IAEtB,QAAQ;IACR,KAAK,EAAE,OAAO;IACd,SAAS,EAAE,WAAW;IAEtB,OAAO;IACP,MAAM,EAAE,QAAQ;IAChB,OAAO,EAAE,SAAS;IAElB,YAAY;IACZ,OAAO,EAAE,SAAS;IAClB,MAAM,EAAE,QAAQ;IAEhB,WAAW;IACX,OAAO,EAAE,SAAS;IAClB,QAAQ,EAAE,UAAU;IACpB,QAAQ,EAAE,UAAU;CACZ,CAAC"}
|
|
1
|
+
{"version":3,"file":"actions.js","sourceRoot":"","sources":["../src/actions.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG;IACrB,YAAY;IACZ,IAAI,EAAE,MAAM;IACZ,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,SAAS;IAClB,QAAQ,EAAE,UAAU;IACpB,UAAU,EAAE,YAAY;IAExB,UAAU;IACV,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,SAAS;IAClB,MAAM,EAAE,QAAQ;IAEhB,WAAW;IACX,EAAE,EAAE,IAAI;IACR,KAAK,EAAE,OAAO;IACd,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,SAAS;IAElB,QAAQ;IACR,GAAG,EAAE,KAAK;IACV,IAAI,EAAE,MAAM;IACZ,KAAK,EAAE,OAAO;IAEd,kBAAkB;IAClB,IAAI,EAAE,MAAM;IACZ,MAAM,EAAE,QAAQ;IAChB,SAAS,EAAE,WAAW;IAEtB,QAAQ;IACR,KAAK,EAAE,OAAO;IACd,SAAS,EAAE,WAAW;IAEtB,OAAO;IACP,MAAM,EAAE,QAAQ;IAChB,OAAO,EAAE,SAAS;IAElB,YAAY;IACZ,OAAO,EAAE,SAAS;IAClB,MAAM,EAAE,QAAQ;IAEhB,WAAW;IACX,OAAO,EAAE,SAAS;IAClB,QAAQ,EAAE,UAAU;IACpB,QAAQ,EAAE,UAAU;IAEpB,eAAe;IACf,MAAM,EAAE,QAAQ;IAChB,QAAQ,EAAE,UAAU;IACpB,MAAM,EAAE,QAAQ;IAChB,QAAQ,EAAE,UAAU;CACZ,CAAC"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Container lifecycle reducer — the first DurableReducer adopter.
|
|
3
|
+
*
|
|
4
|
+
* Extracts the container state machine (previously implicit in Container.ts
|
|
5
|
+
* and ContainerManager.ts) into a pure, testable function. Every legal
|
|
6
|
+
* container lifecycle transition is one case in the switch. Illegal
|
|
7
|
+
* transitions return the input state unchanged.
|
|
8
|
+
*
|
|
9
|
+
* State machine:
|
|
10
|
+
*
|
|
11
|
+
* start
|
|
12
|
+
* ┌──────────┐ ────────────────── ▶ ┌──────────┐
|
|
13
|
+
* │ stopped │ │ starting │
|
|
14
|
+
* └──────────┘ └──────────┘
|
|
15
|
+
* ▲ │ │
|
|
16
|
+
* │ ready │ err │
|
|
17
|
+
* │ ▼ ▼
|
|
18
|
+
* │ ┌─────────┐ ┌─────────┐
|
|
19
|
+
* │ │ running │ │ crashed │
|
|
20
|
+
* │ ◀──── stop/kill ───────────│ │◀─┘ │
|
|
21
|
+
* │ └─────────┘ │
|
|
22
|
+
* │ │ │ ▲ │
|
|
23
|
+
* │ freeze │ │ └──────────────┘
|
|
24
|
+
* │ ▼ │ thaw
|
|
25
|
+
* │ ┌─────────┐
|
|
26
|
+
* │ ◀──── stop/kill ───────────│ frozen │
|
|
27
|
+
* │ └─────────┘
|
|
28
|
+
* │
|
|
29
|
+
* │ health_fail ┌────────────┐
|
|
30
|
+
* │ ◀──── stop/kill ───────────│health-fail │
|
|
31
|
+
* │ └────────────┘
|
|
32
|
+
* │ ▲
|
|
33
|
+
* │ │ health_fail (consecutive)
|
|
34
|
+
* │ │
|
|
35
|
+
* └──────────────────────────── running
|
|
36
|
+
* │
|
|
37
|
+
* │ throttle
|
|
38
|
+
* ▼
|
|
39
|
+
* ┌───────────┐
|
|
40
|
+
* │ throttled │
|
|
41
|
+
* └───────────┘
|
|
42
|
+
*
|
|
43
|
+
* Patent M: Reducer-Based Auditable Cartridge Runtime
|
|
44
|
+
*/
|
|
45
|
+
import type { DurableReducer } from "./durable-reducer.js";
|
|
46
|
+
import { type ActionSchema } from "./action-schema.js";
|
|
47
|
+
export type ContainerStatus = "stopped" | "starting" | "running" | "crashed" | "frozen" | "throttled" | "health-failing";
|
|
48
|
+
export interface ContainerState {
|
|
49
|
+
status: ContainerStatus;
|
|
50
|
+
pid: number | null;
|
|
51
|
+
port: number | null;
|
|
52
|
+
muted: boolean;
|
|
53
|
+
startedAt: number | null;
|
|
54
|
+
updatedAt: number;
|
|
55
|
+
}
|
|
56
|
+
export type ContainerAction = {
|
|
57
|
+
type: "start";
|
|
58
|
+
ts: number;
|
|
59
|
+
} | {
|
|
60
|
+
type: "ready";
|
|
61
|
+
pid: number;
|
|
62
|
+
port?: number;
|
|
63
|
+
ts: number;
|
|
64
|
+
} | {
|
|
65
|
+
type: "stop";
|
|
66
|
+
reason: string;
|
|
67
|
+
ts: number;
|
|
68
|
+
} | {
|
|
69
|
+
type: "crash";
|
|
70
|
+
exitCode: number;
|
|
71
|
+
signal?: string;
|
|
72
|
+
ts: number;
|
|
73
|
+
} | {
|
|
74
|
+
type: "freeze";
|
|
75
|
+
ts: number;
|
|
76
|
+
} | {
|
|
77
|
+
type: "thaw";
|
|
78
|
+
ts: number;
|
|
79
|
+
} | {
|
|
80
|
+
type: "kill";
|
|
81
|
+
reason: string;
|
|
82
|
+
ts: number;
|
|
83
|
+
} | {
|
|
84
|
+
type: "health_fail";
|
|
85
|
+
consecutive: number;
|
|
86
|
+
ts: number;
|
|
87
|
+
} | {
|
|
88
|
+
type: "health_recover";
|
|
89
|
+
ts: number;
|
|
90
|
+
} | {
|
|
91
|
+
type: "mute";
|
|
92
|
+
ts: number;
|
|
93
|
+
} | {
|
|
94
|
+
type: "unmute";
|
|
95
|
+
ts: number;
|
|
96
|
+
} | {
|
|
97
|
+
type: "throttle";
|
|
98
|
+
ts: number;
|
|
99
|
+
} | {
|
|
100
|
+
type: "unthrottle";
|
|
101
|
+
ts: number;
|
|
102
|
+
};
|
|
103
|
+
export declare const containerReducer: DurableReducer<ContainerState, ContainerAction>;
|
|
104
|
+
export declare const containerActionSchema: ActionSchema;
|