@directive-run/core 1.9.0 → 1.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/dist/adapter-utils.d.cts +1 -1
  2. package/dist/adapter-utils.d.ts +1 -1
  3. package/dist/audit-ledger-9IElAHH9.d.ts +205 -0
  4. package/dist/audit-ledger-qMjEBqiP.d.cts +205 -0
  5. package/dist/chunk-26Z5VNPZ.js +16 -0
  6. package/dist/{chunk-FCOZCTLY.js.map → chunk-26Z5VNPZ.js.map} +1 -1
  7. package/dist/chunk-4VZOZWXM.cjs +2 -0
  8. package/dist/chunk-4VZOZWXM.cjs.map +1 -0
  9. package/dist/chunk-7NMXRATK.cjs +3 -0
  10. package/dist/chunk-7NMXRATK.cjs.map +1 -0
  11. package/dist/chunk-7TSYQEN3.js +2 -0
  12. package/dist/chunk-7TSYQEN3.js.map +1 -0
  13. package/dist/{chunk-2OS4RCLV.cjs → chunk-EX3XG667.cjs} +3 -3
  14. package/dist/{chunk-2OS4RCLV.cjs.map → chunk-EX3XG667.cjs.map} +1 -1
  15. package/dist/chunk-TPOKS4RY.js +3 -0
  16. package/dist/chunk-TPOKS4RY.js.map +1 -0
  17. package/dist/{helpers-BwAThjnJ.d.ts → helpers-D2pfb6vT.d.ts} +1 -1
  18. package/dist/{helpers-CG27mEGG.d.cts → helpers-hh6UanB1.d.cts} +1 -1
  19. package/dist/index.cjs +4 -4
  20. package/dist/index.cjs.map +1 -1
  21. package/dist/index.d.cts +344 -4
  22. package/dist/index.d.ts +344 -4
  23. package/dist/index.js +4 -4
  24. package/dist/index.js.map +1 -1
  25. package/dist/internals.cjs +1 -1
  26. package/dist/internals.d.cts +4 -4
  27. package/dist/internals.d.ts +4 -4
  28. package/dist/internals.js +1 -1
  29. package/dist/plugins/index.cjs +2 -2
  30. package/dist/plugins/index.cjs.map +1 -1
  31. package/dist/plugins/index.d.cts +2 -1
  32. package/dist/plugins/index.d.ts +2 -1
  33. package/dist/plugins/index.js +2 -2
  34. package/dist/plugins/index.js.map +1 -1
  35. package/dist/{plugins-DvrsPhzx.d.cts → plugins-Ykl_sAPE.d.cts} +1 -1
  36. package/dist/{plugins-DvrsPhzx.d.ts → plugins-Ykl_sAPE.d.ts} +1 -1
  37. package/dist/system-GK3NSFQH.cjs +2 -0
  38. package/dist/{system-DEMPYZHI.cjs.map → system-GK3NSFQH.cjs.map} +1 -1
  39. package/dist/system-VZWB6WXX.js +2 -0
  40. package/dist/{system-R4JL6U4S.js.map → system-VZWB6WXX.js.map} +1 -1
  41. package/dist/testing.cjs +1 -1
  42. package/dist/testing.d.cts +1 -1
  43. package/dist/testing.d.ts +1 -1
  44. package/dist/testing.js +1 -1
  45. package/dist/worker.cjs +1 -1
  46. package/dist/worker.d.cts +1 -1
  47. package/dist/worker.d.ts +1 -1
  48. package/dist/worker.js +1 -1
  49. package/package.json +1 -1
  50. package/dist/chunk-FCOZCTLY.js +0 -16
  51. package/dist/chunk-WIZHZF4G.cjs +0 -3
  52. package/dist/chunk-WIZHZF4G.cjs.map +0 -1
  53. package/dist/chunk-ZE2RY5KP.js +0 -3
  54. package/dist/chunk-ZE2RY5KP.js.map +0 -1
  55. package/dist/system-DEMPYZHI.cjs +0 -2
  56. package/dist/system-R4JL6U4S.js +0 -2
@@ -1,4 +1,4 @@
1
- import { s as Requirement, p as Plugin, b as Facts, a8 as Schema, H as HistoryAPI, ac as SystemInspection, J as HistoryState } from './plugins-DvrsPhzx.cjs';
1
+ import { t as Requirement, q as Plugin, c as Facts, a8 as Schema, I as HistoryAPI, ac as SystemInspection, K as HistoryState } from './plugins-Ykl_sAPE.cjs';
2
2
  export { s as shallowEqual } from './utils-BnQajqPu.cjs';
3
3
 
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { s as Requirement, p as Plugin, b as Facts, a8 as Schema, H as HistoryAPI, ac as SystemInspection, J as HistoryState } from './plugins-DvrsPhzx.js';
1
+ import { t as Requirement, q as Plugin, c as Facts, a8 as Schema, I as HistoryAPI, ac as SystemInspection, K as HistoryState } from './plugins-Ykl_sAPE.js';
2
2
  export { s as shallowEqual } from './utils-BnQajqPu.js';
3
3
 
4
4
  /**
@@ -0,0 +1,205 @@
1
+ import { b as FactPredicate, C as ClauseResult, q as Plugin, M as ModuleSchema } from './plugins-Ykl_sAPE.js';
2
+
3
+ /**
4
+ * createAuditLedger — append-only, queryable, cryptographically-chained
5
+ * audit of every state change. For compliance, forensics, "show me why
6
+ * this user got that decision."
7
+ *
8
+ * Captures (per observation event):
9
+ *
10
+ * - `constraint.evaluate` → { whenSpec, whenExplain, active }
11
+ * - `resolver.write.rejected` (rejection + summary kinds)
12
+ * - `fact.change` → { key, prior, next }
13
+ * - `resolver.complete` → { resolverId, requirementId, duration }
14
+ * - `system.init` / `system.start` / `system.stop` / `system.destroy`
15
+ *
16
+ * Hash chain: each entry stores `prevHash` (the genesis entry's is null);
17
+ * `hash` is computed *lazily* at `verify()` / `toJSON()` time via
18
+ * `stableStringify` + SHA-256 (`crypto.subtle.digest`). Tampering with
19
+ * any entry's payload breaks the next entry's `prevHash` link — visible
20
+ * in `verify()`.
21
+ *
22
+ * PII redaction: by default, fact keys whose meta carries the `pii`
23
+ * tag (via `system.meta.byTag("pii")`) have their values replaced with
24
+ * `"[redacted]"` in `whenExplain.actual`, `fact.change.prior`, and
25
+ * `fact.change.next`. Opt out with `capturePII: true`.
26
+ */
27
+
28
+ type AuditEntryKind = "constraint.evaluate" | "resolver.write.rejected" | "fact.change" | "resolver.complete" | "resolver.error" | "system.init" | "system.start" | "system.stop" | "system.destroy";
29
+ interface AuditEntryBase {
30
+ /** Monotonic sequence number, starting at 0. */
31
+ readonly seq: number;
32
+ /** Wall-clock timestamp (ms epoch). */
33
+ readonly ts: number;
34
+ /** Discriminator. */
35
+ readonly kind: AuditEntryKind;
36
+ /** Hash of the previous entry's full payload. null on the genesis entry. */
37
+ readonly prevHash: string | null;
38
+ }
39
+ type AuditEntry = (AuditEntryBase & {
40
+ kind: "constraint.evaluate";
41
+ constraintId: string;
42
+ active: boolean;
43
+ /** Cached at ledger start from `system.inspect().constraints[].whenSpec`. May be undefined for function-form constraints. */
44
+ whenSpec?: FactPredicate<unknown>;
45
+ whenExplain?: readonly ClauseResult[];
46
+ }) | (AuditEntryBase & {
47
+ kind: "resolver.write.rejected";
48
+ rejection: "rejection" | "summary";
49
+ resolverId: string;
50
+ requirementId: string;
51
+ reason: string;
52
+ fact?: string;
53
+ expected?: unknown;
54
+ actual?: unknown;
55
+ dropped?: number;
56
+ }) | (AuditEntryBase & {
57
+ kind: "fact.change";
58
+ key: string;
59
+ prior: unknown;
60
+ next: unknown;
61
+ }) | (AuditEntryBase & {
62
+ kind: "resolver.complete";
63
+ resolverId: string;
64
+ requirementId: string;
65
+ duration: number;
66
+ }) | (AuditEntryBase & {
67
+ kind: "resolver.error";
68
+ resolverId: string;
69
+ requirementId: string;
70
+ error: string;
71
+ }) | (AuditEntryBase & {
72
+ kind: "system.init" | "system.start" | "system.stop" | "system.destroy";
73
+ });
74
+ interface QueryFilter {
75
+ /** Exact-match fact path. */
76
+ factPath?: string;
77
+ /** Filter by constraint id. */
78
+ constraintId?: string;
79
+ /** Filter by entry kind. */
80
+ kind?: AuditEntryKind | readonly AuditEntryKind[];
81
+ /** Time range as `[startMs, endMs]`, ISO strings, or epoch numbers. */
82
+ changedBetween?: [string | number | Date, string | number | Date];
83
+ /** Maximum entries returned. Default 1000. */
84
+ limit?: number;
85
+ }
86
+ /** Verify result — chain valid OR a break with full context for tamper visualization. */
87
+ type VerifyResult = {
88
+ valid: true;
89
+ entryCount: number;
90
+ } | {
91
+ valid: false;
92
+ brokenAt: number;
93
+ expectedHash: string;
94
+ actualHash: string;
95
+ entry: AuditEntry;
96
+ };
97
+ interface AuditLedgerSink {
98
+ write(entry: AuditEntry): void;
99
+ query(filter: QueryFilter): readonly AuditEntry[];
100
+ recent(n: number): readonly AuditEntry[];
101
+ forFact(path: string, opts?: {
102
+ limit?: number;
103
+ }): readonly AuditEntry[];
104
+ forConstraint(id: string, opts?: {
105
+ limit?: number;
106
+ }): readonly AuditEntry[];
107
+ toJSON(): {
108
+ entries: readonly AuditEntry[];
109
+ capturedAt: number;
110
+ };
111
+ clear(): void;
112
+ destroy(): void;
113
+ }
114
+ /**
115
+ * In-memory bounded ring-buffer sink. Drops oldest entries past
116
+ * `capacity` (default 10,000). Use this as the default sink for dev,
117
+ * tests, and StackBlitz demos.
118
+ */
119
+ declare function memorySink(opts?: {
120
+ capacity?: number;
121
+ }): AuditLedgerSink;
122
+ interface AuditLedgerOptions {
123
+ /** Sink to write entries to. Default: in-memory ring buffer (capacity 10k). */
124
+ sink?: AuditLedgerSink;
125
+ /**
126
+ * Whether to capture raw fact values (`prior`/`next` on fact.change,
127
+ * `actual` in whenExplain). Default `false` — PII-tagged facts are
128
+ * redacted by default. Set `true` to opt out of redaction.
129
+ */
130
+ capturePII?: boolean;
131
+ /**
132
+ * Optional caller-supplied redactor. Runs AFTER the default
133
+ * pii-tag-based redaction. Useful for additional sanitization.
134
+ */
135
+ redact?: (entry: AuditEntry) => AuditEntry;
136
+ }
137
+ interface AuditLedger {
138
+ /** The plugin to pass to `createSystem({ plugins: [...] })`. */
139
+ readonly plugin: Plugin<ModuleSchema>;
140
+ /** Query entries matching the filter. */
141
+ query(filter?: QueryFilter): readonly AuditEntry[];
142
+ /** Most recent N entries (chronological). */
143
+ recent(n: number): readonly AuditEntry[];
144
+ /** All entries that touch this fact path (exact match). */
145
+ forFact(path: string, opts?: {
146
+ limit?: number;
147
+ }): readonly AuditEntry[];
148
+ /** All entries for this constraint id. */
149
+ forConstraint(id: string, opts?: {
150
+ limit?: number;
151
+ }): readonly AuditEntry[];
152
+ /** Full ledger snapshot for export / serialization. */
153
+ toJSON(): {
154
+ entries: readonly AuditEntry[];
155
+ capturedAt: number;
156
+ };
157
+ /**
158
+ * Walk the hash chain genesis → tip. Returns `{ valid: true }` iff
159
+ * every entry's `prevHash` matches the (sync, djb2-based) hash of
160
+ * the previous entry. On break, returns the index of the first
161
+ * broken link plus the expected vs actual hashes — feed into a
162
+ * "TAMPERED" visualization.
163
+ *
164
+ * Sync by default (djb2 chain). For compliance-grade collision
165
+ * resistance, pass `{ strong: true }` — verify walks the chain a
166
+ * second time with SHA-256 and returns a Promise. Callers must
167
+ * `await` the result when `strong: true` is passed.
168
+ */
169
+ verify(opts?: {
170
+ strong?: boolean;
171
+ }): VerifyResult | Promise<VerifyResult>;
172
+ /** Empty the sink. */
173
+ clear(): void;
174
+ /** Unsubscribe + drop the sink. */
175
+ destroy(): void;
176
+ }
177
+ /**
178
+ * Create an audit ledger that subscribes to the given system's
179
+ * observation stream. Returns a `Plugin` to install + a query/verify
180
+ * API for the ledger.
181
+ *
182
+ * @example
183
+ * ```ts
184
+ * import { createAuditLedger } from "@directive-run/core/plugins";
185
+ *
186
+ * const ledger = createAuditLedger();
187
+ * const system = createSystem({ module, plugins: [ledger.plugin] });
188
+ * system.start();
189
+ *
190
+ * // Six months later — auditor asks "what changed cart-total in March?"
191
+ * ledger.query({
192
+ * factPath: "cartTotal",
193
+ * changedBetween: ["2026-03-01", "2026-04-01"],
194
+ * });
195
+ *
196
+ * // Verify nobody tampered with the ledger
197
+ * const verdict = await ledger.verify();
198
+ * if (!verdict.valid) {
199
+ * console.error("Tamper at entry", verdict.brokenAt);
200
+ * }
201
+ * ```
202
+ */
203
+ declare function createAuditLedger(opts?: AuditLedgerOptions): AuditLedger;
204
+
205
+ export { type AuditEntry as A, type QueryFilter as Q, type AuditEntryKind as a, type AuditLedger as b, type AuditLedgerOptions as c, type AuditLedgerSink as d, createAuditLedger as e, memorySink as m };
@@ -0,0 +1,205 @@
1
+ import { b as FactPredicate, C as ClauseResult, q as Plugin, M as ModuleSchema } from './plugins-Ykl_sAPE.cjs';
2
+
3
+ /**
4
+ * createAuditLedger — append-only, queryable, cryptographically-chained
5
+ * audit of every state change. For compliance, forensics, "show me why
6
+ * this user got that decision."
7
+ *
8
+ * Captures (per observation event):
9
+ *
10
+ * - `constraint.evaluate` → { whenSpec, whenExplain, active }
11
+ * - `resolver.write.rejected` (rejection + summary kinds)
12
+ * - `fact.change` → { key, prior, next }
13
+ * - `resolver.complete` → { resolverId, requirementId, duration }
14
+ * - `system.init` / `system.start` / `system.stop` / `system.destroy`
15
+ *
16
+ * Hash chain: each entry stores `prevHash` (the genesis entry's is null);
17
+ * `hash` is computed *lazily* at `verify()` / `toJSON()` time via
18
+ * `stableStringify` + SHA-256 (`crypto.subtle.digest`). Tampering with
19
+ * any entry's payload breaks the next entry's `prevHash` link — visible
20
+ * in `verify()`.
21
+ *
22
+ * PII redaction: by default, fact keys whose meta carries the `pii`
23
+ * tag (via `system.meta.byTag("pii")`) have their values replaced with
24
+ * `"[redacted]"` in `whenExplain.actual`, `fact.change.prior`, and
25
+ * `fact.change.next`. Opt out with `capturePII: true`.
26
+ */
27
+
28
+ type AuditEntryKind = "constraint.evaluate" | "resolver.write.rejected" | "fact.change" | "resolver.complete" | "resolver.error" | "system.init" | "system.start" | "system.stop" | "system.destroy";
29
+ interface AuditEntryBase {
30
+ /** Monotonic sequence number, starting at 0. */
31
+ readonly seq: number;
32
+ /** Wall-clock timestamp (ms epoch). */
33
+ readonly ts: number;
34
+ /** Discriminator. */
35
+ readonly kind: AuditEntryKind;
36
+ /** Hash of the previous entry's full payload. null on the genesis entry. */
37
+ readonly prevHash: string | null;
38
+ }
39
+ type AuditEntry = (AuditEntryBase & {
40
+ kind: "constraint.evaluate";
41
+ constraintId: string;
42
+ active: boolean;
43
+ /** Cached at ledger start from `system.inspect().constraints[].whenSpec`. May be undefined for function-form constraints. */
44
+ whenSpec?: FactPredicate<unknown>;
45
+ whenExplain?: readonly ClauseResult[];
46
+ }) | (AuditEntryBase & {
47
+ kind: "resolver.write.rejected";
48
+ rejection: "rejection" | "summary";
49
+ resolverId: string;
50
+ requirementId: string;
51
+ reason: string;
52
+ fact?: string;
53
+ expected?: unknown;
54
+ actual?: unknown;
55
+ dropped?: number;
56
+ }) | (AuditEntryBase & {
57
+ kind: "fact.change";
58
+ key: string;
59
+ prior: unknown;
60
+ next: unknown;
61
+ }) | (AuditEntryBase & {
62
+ kind: "resolver.complete";
63
+ resolverId: string;
64
+ requirementId: string;
65
+ duration: number;
66
+ }) | (AuditEntryBase & {
67
+ kind: "resolver.error";
68
+ resolverId: string;
69
+ requirementId: string;
70
+ error: string;
71
+ }) | (AuditEntryBase & {
72
+ kind: "system.init" | "system.start" | "system.stop" | "system.destroy";
73
+ });
74
+ interface QueryFilter {
75
+ /** Exact-match fact path. */
76
+ factPath?: string;
77
+ /** Filter by constraint id. */
78
+ constraintId?: string;
79
+ /** Filter by entry kind. */
80
+ kind?: AuditEntryKind | readonly AuditEntryKind[];
81
+ /** Time range as `[startMs, endMs]`, ISO strings, or epoch numbers. */
82
+ changedBetween?: [string | number | Date, string | number | Date];
83
+ /** Maximum entries returned. Default 1000. */
84
+ limit?: number;
85
+ }
86
+ /** Verify result — chain valid OR a break with full context for tamper visualization. */
87
+ type VerifyResult = {
88
+ valid: true;
89
+ entryCount: number;
90
+ } | {
91
+ valid: false;
92
+ brokenAt: number;
93
+ expectedHash: string;
94
+ actualHash: string;
95
+ entry: AuditEntry;
96
+ };
97
+ interface AuditLedgerSink {
98
+ write(entry: AuditEntry): void;
99
+ query(filter: QueryFilter): readonly AuditEntry[];
100
+ recent(n: number): readonly AuditEntry[];
101
+ forFact(path: string, opts?: {
102
+ limit?: number;
103
+ }): readonly AuditEntry[];
104
+ forConstraint(id: string, opts?: {
105
+ limit?: number;
106
+ }): readonly AuditEntry[];
107
+ toJSON(): {
108
+ entries: readonly AuditEntry[];
109
+ capturedAt: number;
110
+ };
111
+ clear(): void;
112
+ destroy(): void;
113
+ }
114
+ /**
115
+ * In-memory bounded ring-buffer sink. Drops oldest entries past
116
+ * `capacity` (default 10,000). Use this as the default sink for dev,
117
+ * tests, and StackBlitz demos.
118
+ */
119
+ declare function memorySink(opts?: {
120
+ capacity?: number;
121
+ }): AuditLedgerSink;
122
+ interface AuditLedgerOptions {
123
+ /** Sink to write entries to. Default: in-memory ring buffer (capacity 10k). */
124
+ sink?: AuditLedgerSink;
125
+ /**
126
+ * Whether to capture raw fact values (`prior`/`next` on fact.change,
127
+ * `actual` in whenExplain). Default `false` — PII-tagged facts are
128
+ * redacted by default. Set `true` to opt out of redaction.
129
+ */
130
+ capturePII?: boolean;
131
+ /**
132
+ * Optional caller-supplied redactor. Runs AFTER the default
133
+ * pii-tag-based redaction. Useful for additional sanitization.
134
+ */
135
+ redact?: (entry: AuditEntry) => AuditEntry;
136
+ }
137
+ interface AuditLedger {
138
+ /** The plugin to pass to `createSystem({ plugins: [...] })`. */
139
+ readonly plugin: Plugin<ModuleSchema>;
140
+ /** Query entries matching the filter. */
141
+ query(filter?: QueryFilter): readonly AuditEntry[];
142
+ /** Most recent N entries (chronological). */
143
+ recent(n: number): readonly AuditEntry[];
144
+ /** All entries that touch this fact path (exact match). */
145
+ forFact(path: string, opts?: {
146
+ limit?: number;
147
+ }): readonly AuditEntry[];
148
+ /** All entries for this constraint id. */
149
+ forConstraint(id: string, opts?: {
150
+ limit?: number;
151
+ }): readonly AuditEntry[];
152
+ /** Full ledger snapshot for export / serialization. */
153
+ toJSON(): {
154
+ entries: readonly AuditEntry[];
155
+ capturedAt: number;
156
+ };
157
+ /**
158
+ * Walk the hash chain genesis → tip. Returns `{ valid: true }` iff
159
+ * every entry's `prevHash` matches the (sync, djb2-based) hash of
160
+ * the previous entry. On break, returns the index of the first
161
+ * broken link plus the expected vs actual hashes — feed into a
162
+ * "TAMPERED" visualization.
163
+ *
164
+ * Sync by default (djb2 chain). For compliance-grade collision
165
+ * resistance, pass `{ strong: true }` — verify walks the chain a
166
+ * second time with SHA-256 and returns a Promise. Callers must
167
+ * `await` the result when `strong: true` is passed.
168
+ */
169
+ verify(opts?: {
170
+ strong?: boolean;
171
+ }): VerifyResult | Promise<VerifyResult>;
172
+ /** Empty the sink. */
173
+ clear(): void;
174
+ /** Unsubscribe + drop the sink. */
175
+ destroy(): void;
176
+ }
177
+ /**
178
+ * Create an audit ledger that subscribes to the given system's
179
+ * observation stream. Returns a `Plugin` to install + a query/verify
180
+ * API for the ledger.
181
+ *
182
+ * @example
183
+ * ```ts
184
+ * import { createAuditLedger } from "@directive-run/core/plugins";
185
+ *
186
+ * const ledger = createAuditLedger();
187
+ * const system = createSystem({ module, plugins: [ledger.plugin] });
188
+ * system.start();
189
+ *
190
+ * // Six months later — auditor asks "what changed cart-total in March?"
191
+ * ledger.query({
192
+ * factPath: "cartTotal",
193
+ * changedBetween: ["2026-03-01", "2026-04-01"],
194
+ * });
195
+ *
196
+ * // Verify nobody tampered with the ledger
197
+ * const verdict = await ledger.verify();
198
+ * if (!verdict.valid) {
199
+ * console.error("Tamper at entry", verdict.brokenAt);
200
+ * }
201
+ * ```
202
+ */
203
+ declare function createAuditLedger(opts?: AuditLedgerOptions): AuditLedger;
204
+
205
+ export { type AuditEntry as A, type QueryFilter as Q, type AuditEntryKind as a, type AuditLedger as b, type AuditLedgerOptions as c, type AuditLedgerSink as d, createAuditLedger as e, memorySink as m };
@@ -0,0 +1,16 @@
1
+ import {T,j,h,o,u,q,t}from'./chunk-TPOKS4RY.js';import {a,l,m as m$1,n}from'./chunk-TZHC4E6S.js';import {e,a as a$1}from'./chunk-T6IJUWYR.js';var m="::",he=Symbol.for("nodejs.util.inspect.custom");function we(e){if(!e.ownKeys)return {};let n={};for(let t of e.ownKeys())n[t]=e.get(t);return n}function D(e){return new Proxy({},{get(n,t){if(typeof t=="symbol")return t===he?()=>we(e):void 0;if(!l.has(t))return e.get(t)},set(n,t,s){return typeof t=="symbol"||l.has(t)?false:e.set?e.set(t,s):false},has(n,t){return typeof t=="symbol"||l.has(t)?false:e.has?e.has(t):false},deleteProperty(n,t){return typeof t=="symbol"||l.has(t)?false:e.delete?e.delete(t):false},ownKeys(){return e.ownKeys?e.ownKeys():[]},getOwnPropertyDescriptor(n,t){if(typeof t!="symbol"&&e.has&&typeof t=="string"&&e.has(t))return {configurable:true,enumerable:true}},defineProperty(){return false},getPrototypeOf(){return null},setPrototypeOf(){return false}})}var Z=new WeakMap,Q=new WeakMap,X=new WeakMap,ee=new WeakMap,ne=new WeakMap,te=new WeakMap;function $(e,n$1){let t=Z.get(e);if(t){let r=t.get(n$1);if(r)return r}else t=new Map,Z.set(e,t);let s=D({get:r=>r==="$store"||r==="$snapshot"?e[r]:e[`${n$1}${m}${r}`],set:(r,u)=>{if(a){let i=m$1(u);i&&n(`${n$1}.${r}`,i);}return e[`${n$1}${m}${r}`]=u,true},has:r=>`${n$1}${m}${r}`in e,delete:r=>(delete e[`${n$1}${m}${r}`],true)});return t.set(n$1,s),s}function re(e,n,t){let s=Q.get(e);if(s)return s;let r=D({get:u=>{if(Object.hasOwn(n,u))return $(e,u)},has:u=>Object.hasOwn(n,u),ownKeys:()=>t()});return Q.set(e,r),r}function oe(e,n,t){let s=`${n}|${t.join(",")}`,r=ne.get(e);if(r){let o=r.get(s);if(o)return o}else r=new Map,ne.set(e,r);let u=new Set(t),i=["self",...t],c=D({get:o=>{if(o==="self")return $(e,n);if(u.has(o))return $(e,o);a&&console.warn(`[Directive] Module "${n}" accessed undeclared cross-module property "${o}". Add it to crossModuleDeps or use "facts.self.${o}" for own module facts.`);},has:o=>o==="self"||u.has(o),ownKeys:()=>i});return r.set(s,c),c}function B(e,n){let t=ee.get(e);if(t){let r=t.get(n);if(r)return r}else t=new Map,ee.set(e,t);let s=D({get:r=>e[`${n}${m}${r}`],has:r=>`${n}${m}${r}`in e});return t.set(n,s),s}function se(e,n,t){let s=X.get(e);if(s)return s;let r=D({get:u=>{if(Object.hasOwn(n,u))return B(e,u)},has:u=>Object.hasOwn(n,u),ownKeys:()=>t()});return X.set(e,r),r}function ie(e,n,t){let s=te.get(e);return s||(s=new Map,te.set(e,s)),D({get:r=>{if(!Object.hasOwn(n,r))return;let u=s.get(r);if(u)return u;let i=D({get:c=>o=>{e.dispatch({type:`${r}${m}${c}`,...o});}});return s.set(r,i),i},has:r=>Object.hasOwn(n,r),ownKeys:()=>t()})}function R(e){if(e.includes(".")){let[n,...t]=e.split(".");return `${n}${m}${t.join(m)}`}return e}function H(e){let n={};for(let[t,s]of Object.entries(e)){let r=t.indexOf(m);if(r>0){let u=t.slice(0,r),i=t.slice(r+m.length);n[u]||(n[u]={}),n[u][i]=s;}else n._root||(n._root={}),n._root[t]=s;}return n}function P(e,n,t,s){return t?oe(e,n,s):$(e,n)}function b(e,n){return `${e}${m}${n}`}function ae(e){return e.includes(m)}function E(e,n,t){if(Array.isArray(e)){let i=e.map(c=>{if(c&&typeof c=="object"&&typeof c.fact=="string"){let o=c.fact;return ae(o)?c:{...c,fact:b(n,o)}}return c});return a$1(i),i}if(!e||typeof e!="object")return e;let s=e;if("$all"in s||"$any"in s){let i="$all"in s?"$all":"$any",c=s[i],o={[i]:c.map(f=>E(f,n,t))};return a$1(o),o}if("$not"in s){let i={$not:E(s.$not,n,t)};return a$1(i),i}function r(i,c){return E(i,c,ce)}let u={};for(let i of Object.keys(s)){if(i.startsWith("$")||ae(i)){u[i]=s[i];continue}if(i==="self"){let c=s[i];if(c&&typeof c=="object"){let o=r(c,n);if(o&&typeof o=="object"&&!Array.isArray(o)){for(let[f,l]of Object.entries(o))u[f]=l;continue}}}if(t.has(i)){let c=s[i];if(c&&typeof c=="object"){let o=r(c,i);if(o&&typeof o=="object"&&!Array.isArray(o)){for(let[f,l]of Object.entries(o))u[f]=l;continue}}}u[b(n,i)]=s[i];}return a$1(u),u}var ce=new Set;function me(e,n){let t$1=e.crossModuleDeps?new Set(Object.keys(e.crossModuleDeps)):ce,s=e.constraints;if(s){let c=false,o={};for(let[f,l]of Object.entries(s)){let d=l;if(d.when!==void 0&&typeof d.when!="function"){o[f]={...d,when:E(d.when,n,t$1)},c=true;continue}o[f]=l;}c&&(s=o);}let r=e.derive;if(r){let c=false,o$1={};for(let[f,l]of Object.entries(r)){let d=l&&typeof l=="object"&&Object.hasOwn(l,"compute")?l:null;if(!d){o$1[f]=l;continue}let g=d.compute;if(typeof g=="function"){o$1[f]=l;continue}if(j(g)){a$1(g);let k=w=>q(g,w);o$1[f]=d.meta?{compute:k,meta:d.meta}:k,c=true;continue}if(h(g)){a$1(g);let k=o(g),w=j=>k(j);o$1[f]=d.meta?{compute:w,meta:d.meta}:w,c=true;continue}o$1[f]=l;}c&&(r=o$1);}let u=e.events;if(u){let c=false,o={};for(let[f,l]of Object.entries(u)){if(l&&typeof l=="object"){let d=Object.hasOwn(l,"handler"),g=Object.hasOwn(l,"patch");if(d&&g&&a&&console.warn(`[Directive] event "${f}": both \`handler\` and \`patch\` provided \u2014 using \`handler\` (patch is ignored).`),g&&!d){let k=l;a$1(k.patch);let w=(j,O)=>t(k.patch,j,O??{});o[f]=k.meta?{handler:w,meta:k.meta}:w,c=true;continue}}o[f]=l;}c&&(u=o);}let i=e.effects;if(i){let c=false,o={};for(let[f,l]of Object.entries(i)){let d=l;if(d.on!==void 0&&h(d.on)){o[f]={...d,on:E(d.on,n,t$1)},c=true;continue}o[f]=l;}c&&(i=o);}return s===e.constraints&&r===e.derive&&u===e.events&&i===e.effects?e:{...e,constraints:s,derive:r,events:u,effects:i}}function C(e){return Object.keys(e).length>0?e:void 0}function ke(e,n){let t={};for(let[s,r]of Object.entries(e.schema.facts))t[b(n,s)]=r;return t}function pe(e,n){if(e.init)return t=>{let s=$(t,n);e.init(s);}}function ve(e,n,t,s){if(!e.derive)return;let r={};for(let[u$1,i]of Object.entries(e.derive)){let c=u(i),o=c?i.compute:i,f=c?i.meta:void 0,l=(d,g)=>{let k=P(d,n,t,s),w=B(g,n);return o(k,w)};r[b(n,u$1)]=f?{compute:l,meta:f}:l;}return C(r)}function be(e,n){if(!e.events)return;let t={};for(let[s,r]of Object.entries(e.events)){let u=typeof r=="object"&&r!==null&&Object.hasOwn(r,"handler"),i=u?r.handler:r,c=u?r.meta:void 0,o=(f,l)=>{let d=$(f,n);i(d,l);};t[b(n,s)]=c?{handler:o,meta:c}:o;}return C(t)}function Me(e,n,t,s){if(!e.constraints)return;let r={};for(let[u,i]of Object.entries(e.constraints)){let c=i,o=typeof c.when=="function";r[b(n,u)]={...c,deps:c.deps?.map(f=>b(n,f)),after:c.after?.map(f=>f.includes(m)?f:b(n,f)),owns:c.owns?.map(f=>f.includes(m)?f:b(n,f)),when:o?f=>{let l=P(f,n,t,s);return c.when(l)}:c.when,require:typeof c.require=="function"?f=>{let l=P(f,n,t,s);return c.require(l)}:c.require};}return C(r)}function Re(e,n,t,s){if(!e.resolvers)return;let r={};for(let[i,c]of Object.entries(e.resolvers)){let f=function(l){return {facts:P(l.facts,n,t,s),signal:l.signal}};let o=c;r[b(n,i)]={...o,...o.resolve&&{resolve:async(l,d)=>{await o.resolve(l,f(d));}},...o.resolveBatch&&{resolveBatch:async(l,d)=>{await o.resolveBatch(l,f(d));}},...o.resolveBatchWithResults&&{resolveBatchWithResults:async(l,d)=>o.resolveBatchWithResults(l,f(d))}};}return C(r)}function Se(e,n,t,s){if(!e.effects)return;let r={};for(let[u,i]of Object.entries(e.effects)){let c=i;r[b(n,u)]={...c,run:(o,f)=>{let l=P(o,n,t,s),d=f?P(f,n,t,s):void 0;return c.run(l,d)},deps:c.deps?.map(o=>b(n,o))};}return C(r)}function Oe(e,n,t){return {snapshotEvents:t&&!t.has(n)?[]:e.history?.snapshotEvents?.map(s=>b(n,s))}}function I(e){let{mod:n,namespace:t,snapshotModulesSet:s}=e,r=me(n,t),u=!!(r.crossModuleDeps&&Object.keys(r.crossModuleDeps).length>0),i=u?Object.keys(r.crossModuleDeps):[];return {id:r.id,schema:ke(r,t),requirements:r.schema.requirements??{},init:pe(r,t),derive:ve(r,t,u,i),events:be(r,t),effects:Se(r,t,u,i),constraints:Me(r,t,u,i),resolvers:Re(r,t,u,i),hooks:r.hooks,meta:r.meta,history:Oe(r,t,s)}}function xe(e){let n=Object.keys(e),t=new Set(n),s=new Set,r=new Set,u=[],i=[];function c(o){if(s.has(o))return;if(r.has(o)){let l=i.indexOf(o),d=[...i.slice(l),o].join(" \u2192 ");throw new Error(`[Directive] Circular dependency detected: ${d}. Modules cannot have circular crossModuleDeps. Break the cycle by removing one of the cross-module references.`)}r.add(o),i.push(o);let f=e[o];if(f?.crossModuleDeps)for(let l of Object.keys(f.crossModuleDeps))t.has(l)&&c(l);i.pop(),r.delete(o),s.add(o),u.push(o);}for(let o of n)c(o);return u}function ue(e,n){let t=[];for(let s of Object.keys(n.schema.facts))t.push(`${e}${m}${s}`);if(n.schema.derivations)for(let s of Object.keys(n.schema.derivations))t.push(`${e}${m}${s}`);return t}function ze(e){if("module"in e){if(!e.module)throw new Error("[Directive] createSystem requires a module. Got: "+typeof e.module);return $e(e)}let n=e;if(Array.isArray(n.modules))throw new Error(`[Directive] createSystem expects modules as an object, not an array.
2
+
3
+ Instead of:
4
+ createSystem({ modules: [authModule, dataModule] })
5
+
6
+ Use:
7
+ createSystem({ modules: { auth: authModule, data: dataModule } })
8
+
9
+ Or for a single module:
10
+ createSystem({ module: counterModule })`);let t=n.modules;if(t&&typeof t=="object"&&"id"in t&&"schema"in t)throw new Error(`[Directive] A single module was passed to \`modules:\`. For a single module, use \`module:\` instead:
11
+
12
+ createSystem({ module: myModule })
13
+
14
+ For multiple modules, wrap in an object:
15
+ createSystem({ modules: { myName: myModule } })`);return De(n)}function De(e$1){let n=e$1.modules,t=new Set(Object.keys(n)),s=typeof e$1.history=="object"?e$1.history:null,r=s?.snapshotModules?new Set(s.snapshotModules):null;if(e$1.tickMs!==void 0&&e$1.tickMs<=0)throw new Error("[Directive] tickMs must be a positive number");if(a){for(let[a,y]of Object.entries(n))if(y.crossModuleDeps)for(let h of Object.keys(y.crossModuleDeps))h===a?console.warn(`[Directive] Module "${a}" references itself in crossModuleDeps. Use "facts.self" to access own module's facts instead.`):t.has(h)||console.warn(`[Directive] Module "${a}" declares crossModuleDeps.${h}, but no module with namespace "${h}" exists in the system. Available modules: ${[...t].join(", ")}`);}if(a&&s?.snapshotModules)for(let a of s.snapshotModules)t.has(a)||console.warn(`[Directive] history.snapshotModules entry "${a}" doesn't match any module. Available modules: ${[...t].join(", ")}`);let u,i=e$1.initOrder??"auto";if(Array.isArray(i)){let a=i,y=Object.keys(n).filter(h=>!a.includes(h));if(y.length>0)throw new Error(`[Directive] initOrder is missing modules: ${y.join(", ")}. All modules must be included in the explicit order.`);u=a;}else i==="declaration"?u=Object.keys(n):u=xe(n);let{history:c,trace:o,errorBoundary:f}=de(e$1);for(let a of Object.keys(n)){if(a.includes(m))throw new Error(`[Directive] Module name "${a}" contains the reserved separator "${m}". Module names cannot contain "${m}".`);let y=n[a];if(y){for(let h of Object.keys(y.schema.facts))if(h.includes(m))throw new Error(`[Directive] Schema key "${h}" in module "${a}" contains the reserved separator "${m}". Schema keys cannot contain "${m}".`)}}let l$1={names:null};function d(){return l$1.names===null&&(l$1.names=Object.keys(n)),l$1.names}let g=u.map(a=>{let y=n[a];return y?I({mod:y,namespace:a,snapshotModulesSet:r}):null}).filter(a=>a!==null);a&&e$1.tickMs&&e$1.tickMs>0&&(g.some(y=>y.events&&Object.keys(y.events).some(h=>h.endsWith(`${m}tick`)))||console.warn(`[Directive] tickMs is set to ${e$1.tickMs}ms but no module defines a "tick" event handler.`));let k=null,w=null;function j(a$1){for(let[y,h]of Object.entries(a$1)){if(l.has(y)){a&&console.warn(`[Directive] initialFacts/hydrate contains blocked namespace "${y}". Skipping.`);continue}if(!t.has(y)){a&&console.warn(`[Directive] initialFacts/hydrate contains unknown namespace "${y}". Available modules: ${[...t].join(", ")}`);continue}if(h&&typeof h=="object"&&!e(h))throw new Error(`[Directive] initialFacts/hydrate for namespace "${y}" contains potentially dangerous keys (__proto__, constructor, or prototype). This may indicate a prototype pollution attack.`);for(let[M,x]of Object.entries(h))l.has(M)||(w.facts[`${y}${m}${M}`]=x);}}w=T({modules:g,plugins:e$1.plugins,history:c,trace:o,errorBoundary:f,tickMs:e$1.tickMs,cloud:e$1.cloud,onAfterModuleInit:()=>{e$1.initialFacts&&j(e$1.initialFacts),k&&(j(k),k=null);}});let O=new Map;for(let a of Object.keys(n)){let y=n[a];y&&O.set(a,ue(a,y));}let q=re(w.facts,n,d),ye=se(w.derive,n,d),ge=ie(w,n,d),A=null,F=e$1.tickMs,_={_mode:"namespaced",facts:q,history:w.history,derive:ye,events:ge,constraints:w.constraints,effects:w.effects,resolvers:w.resolvers,async hydrate(a){if(w.isRunning)throw new Error("[Directive] hydrate() must be called before start(). The system is already running.");let y=await a();y&&typeof y=="object"&&(k=y);},initialize(){w.initialize();},start(){if(w.start(),F&&F>0){let a;for(let y of g)if(y?.events&&(a=Object.keys(y.events).find(h=>h.endsWith(`${m}tick`)),a))break;if(a){let y=a;A=setInterval(()=>{w.dispatch({type:y});},F);}}},stop(){A&&(clearInterval(A),A=null),w.stop();},destroy(){this.stop(),w.destroy();},dispatch(a){w.dispatch(a);},read(a){return w.read(R(a))},subscribe(a$1,y){let h=[];for(let M of a$1)if(M.endsWith(".*")){let x=M.slice(0,-2),W=O.get(x);W?h.push(...W):a&&console.warn(`[Directive] subscribe wildcard "${M}" \u2014 namespace "${x}" not found.`);}else h.push(R(M));return w.subscribe(h,y)},subscribeModule(a$1,y){let h=O.get(a$1);return !h||h.length===0?(a&&console.warn(`[Directive] subscribeModule("${a$1}") \u2014 namespace not found. Available: ${[...O.keys()].join(", ")}`),()=>{}):w.subscribe(h,y)},watch(a,y,h){return w.watch(R(a),y,h)},when(a,y){return w.when(()=>a(q),y)},getDistributableSnapshot(a){let y={...a,includeDerivations:a?.includeDerivations?.map(R),excludeDerivations:a?.excludeDerivations?.map(R),includeFacts:a?.includeFacts?.map(R)},h=w.getDistributableSnapshot(y);return {...h,data:H(h.data)}},watchDistributableSnapshot(a,y){let h={...a,includeDerivations:a?.includeDerivations?.map(R),excludeDerivations:a?.excludeDerivations?.map(R),includeFacts:a?.includeFacts?.map(R)};return w.watchDistributableSnapshot(h,M=>{y({...M,data:H(M.data)});})},registerModule(a,y){if(t.has(a))throw new Error(`[Directive] Module namespace "${a}" already exists. Cannot register a duplicate namespace.`);if(a.includes(m))throw new Error(`[Directive] Module name "${a}" contains the reserved separator "${m}".`);if(l.has(a))throw new Error(`[Directive] Module name "${a}" is a blocked property.`);for(let x of Object.keys(y.schema.facts))if(x.includes(m))throw new Error(`[Directive] Schema key "${x}" in module "${a}" contains the reserved separator "${m}".`);let h=y,M=I({mod:h,namespace:a,snapshotModulesSet:r});t.add(a),n[a]=h,l$1.names=null,O.set(a,ue(a,h)),w.registerModule(M);}};return le(_,w),fe(_),_}function de(e){let n=e.history,t=e.trace,s=e.errorBoundary;return e.zeroConfig&&(n=n??a,s={onConstraintError:"skip",onResolverError:"skip",onEffectError:"skip",onDerivationError:"skip",...e.errorBoundary}),{history:n,trace:t,errorBoundary:s}}function le(e,n){Object.defineProperties(e,{trace:{get(){return n.trace},enumerable:true,configurable:true},meta:{value:n.meta,enumerable:true,configurable:true},isRunning:{get(){return n.isRunning},enumerable:true,configurable:true},isSettled:{get(){return n.isSettled},enumerable:true,configurable:true},isInitialized:{get(){return n.isInitialized},enumerable:true,configurable:true},isReady:{get(){return n.isReady},enumerable:true,configurable:true}}),e.whenReady=n.whenReady.bind(n),e.batch=n.batch.bind(n),e.onSettledChange=n.onSettledChange.bind(n),e.onHistoryChange=n.onHistoryChange.bind(n),e.inspect=n.inspect.bind(n),e.settle=n.settle.bind(n),e.explain=n.explain.bind(n),e.getSnapshot=n.getSnapshot.bind(n),e.restore=n.restore.bind(n),e.observe=n.observe.bind(n);let t=["dispatch","read","subscribe","watch","when","getDistributableSnapshot","watchDistributableSnapshot"];for(let s of t)s in e||(e[s]=n[s].bind(n));}function fe(e){a&&(typeof process>"u"||process.env?.NODE_ENV!=="test")&&setTimeout(()=>{!e.isRunning&&!e.isInitialized&&console.warn("[Directive] System created but start() was never called. Constraints, resolvers, and effects will not run until you call system.start().");},0);}function $e(e$1){let n=e$1.module;if(!n)throw new Error("[Directive] createSystem requires a module. Got: "+typeof n);if(e$1.tickMs!==void 0&&e$1.tickMs<=0)throw new Error("[Directive] tickMs must be a positive number");if(e$1.initialFacts&&!e(e$1.initialFacts))throw new Error("[Directive] initialFacts contains potentially dangerous keys (__proto__, constructor, or prototype). This may indicate a prototype pollution attack.");a&&(n.crossModuleDeps&&Object.keys(n.crossModuleDeps).length>0&&console.warn("[Directive] Single module mode ignores crossModuleDeps. Use multiple modules if cross-module access is needed: createSystem({ modules: { ... } })"),e$1.tickMs&&e$1.tickMs>0&&(n.events&&"tick"in n.events||console.warn(`[Directive] tickMs is set to ${e$1.tickMs}ms but module has no "tick" event handler.`)),(typeof e$1.history=="object"?e$1.history:null)?.snapshotModules&&console.warn("[Directive] history.snapshotModules has no effect in single-module mode. Use history.snapshotEvents on the module definition instead, or switch to createSystem({ modules: { ... } }) for multi-module filtering."));let{history:t,trace:s,errorBoundary:r}=de(e$1),u=null,i=null;i=T({modules:[{id:n.id,schema:n.schema.facts,requirements:n.schema.requirements,init:n.init,derive:n.derive,events:n.events,effects:n.effects,constraints:n.constraints,resolvers:n.resolvers,hooks:n.hooks,meta:n.meta,history:n.history}],plugins:e$1.plugins,history:t,trace:s,errorBoundary:r,tickMs:e$1.tickMs,cloud:e$1.cloud,onAfterModuleInit:()=>{if(e$1.initialFacts)for(let[d,g]of Object.entries(e$1.initialFacts))l.has(d)||(i.facts[d]=g);if(u){if(!e(u))a&&console.warn("[Directive] hydrate() data contains potentially dangerous keys. Skipping.");else for(let[d,g]of Object.entries(u))l.has(d)||(i.facts[d]=g);u=null;}}});let c=new Proxy({},{get(d,g){if(typeof g!="symbol"&&!l.has(g))return k=>{i.dispatch({type:g,...k});}},has(d,g){return typeof g=="symbol"||l.has(g)?false:n.events?g in n.events:false},ownKeys(){return n.events?Object.keys(n.events):[]},getOwnPropertyDescriptor(d,g){if(typeof g!="symbol"&&!l.has(g)&&n.events&&g in n.events)return {configurable:true,enumerable:true}},set(){return false},deleteProperty(){return false},defineProperty(){return false},getPrototypeOf(){return null},setPrototypeOf(){return false}}),o=null,f=e$1.tickMs,l$1={_mode:"single",facts:i.facts,history:i.history,derive:i.derive,events:c,constraints:i.constraints,effects:i.effects,resolvers:i.resolvers,async hydrate(d){if(i.isRunning)throw new Error("[Directive] hydrate() must be called before start(). The system is already running.");let g=await d();g&&typeof g=="object"&&(u=g);},initialize(){i.initialize();},start(){i.start(),f&&f>0&&n.events&&"tick"in n.events&&(o=setInterval(()=>{i.dispatch({type:"tick"});},f));},stop(){o&&(clearInterval(o),o=null),i.stop();},destroy(){this.stop(),i.destroy();},registerModule(d){i.registerModule({id:d.id,schema:d.schema.facts,requirements:d.schema.requirements,init:d.init,derive:d.derive,events:d.events,effects:d.effects,constraints:d.constraints,resolvers:d.resolvers,hooks:d.hooks,history:d.history});}};return le(l$1,i),fe(l$1),l$1}export{ze as a};//# sourceMappingURL=chunk-26Z5VNPZ.js.map
16
+ //# sourceMappingURL=chunk-26Z5VNPZ.js.map