@smthrs/journal 0.0.0-stage → 1.0.0-rc.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +149 -0
- package/LICENSE +21 -0
- package/README.md +206 -2
- package/dist/cjs/CallFact.d.ts +129 -0
- package/dist/cjs/CallFact.d.ts.map +1 -0
- package/dist/cjs/CallFact.js +106 -0
- package/dist/cjs/CallFact.js.map +7 -0
- package/dist/cjs/Consensus.d.ts +440 -0
- package/dist/cjs/Consensus.d.ts.map +1 -0
- package/dist/cjs/Consensus.js +251 -0
- package/dist/cjs/Consensus.js.map +7 -0
- package/dist/cjs/EngineEvent.d.ts +890 -0
- package/dist/cjs/EngineEvent.d.ts.map +1 -0
- package/dist/cjs/EngineEvent.js +383 -0
- package/dist/cjs/EngineEvent.js.map +7 -0
- package/dist/cjs/ExecutionFact.d.ts +216 -0
- package/dist/cjs/ExecutionFact.d.ts.map +1 -0
- package/dist/cjs/ExecutionFact.js +303 -0
- package/dist/cjs/ExecutionFact.js.map +7 -0
- package/dist/cjs/Journal.d.ts +617 -0
- package/dist/cjs/Journal.d.ts.map +1 -0
- package/dist/cjs/Journal.js +190 -0
- package/dist/cjs/Journal.js.map +7 -0
- package/dist/cjs/JournalEvent.d.ts +421 -0
- package/dist/cjs/JournalEvent.d.ts.map +1 -0
- package/dist/cjs/JournalEvent.js +281 -0
- package/dist/cjs/JournalEvent.js.map +7 -0
- package/dist/cjs/JournalGeneration.d.ts +34 -0
- package/dist/cjs/JournalGeneration.d.ts.map +1 -0
- package/dist/cjs/JournalGeneration.js +72 -0
- package/dist/cjs/JournalGeneration.js.map +7 -0
- package/dist/cjs/JournalMetrics.d.ts +72 -0
- package/dist/cjs/JournalMetrics.d.ts.map +1 -0
- package/dist/cjs/JournalMetrics.js +55 -0
- package/dist/cjs/JournalMetrics.js.map +7 -0
- package/dist/cjs/Migrations.d.ts +42 -0
- package/dist/cjs/Migrations.d.ts.map +1 -0
- package/dist/cjs/Migrations.js +58 -0
- package/dist/cjs/Migrations.js.map +7 -0
- package/dist/cjs/OwnerId.d.ts +40 -0
- package/dist/cjs/OwnerId.d.ts.map +1 -0
- package/dist/cjs/OwnerId.js +40 -0
- package/dist/cjs/OwnerId.js.map +7 -0
- package/dist/cjs/Projection.d.ts +29 -0
- package/dist/cjs/Projection.d.ts.map +1 -0
- package/dist/cjs/Projection.js +25 -0
- package/dist/cjs/Projection.js.map +7 -0
- package/dist/cjs/RedactedLogger.d.ts +121 -0
- package/dist/cjs/RedactedLogger.d.ts.map +1 -0
- package/dist/cjs/RedactedLogger.js +235 -0
- package/dist/cjs/RedactedLogger.js.map +7 -0
- package/dist/cjs/Redaction.d.ts +350 -0
- package/dist/cjs/Redaction.d.ts.map +1 -0
- package/dist/cjs/Redaction.js +928 -0
- package/dist/cjs/Redaction.js.map +7 -0
- package/dist/cjs/SqlConsensus.d.ts +44 -0
- package/dist/cjs/SqlConsensus.d.ts.map +1 -0
- package/dist/cjs/SqlConsensus.js +243 -0
- package/dist/cjs/SqlConsensus.js.map +7 -0
- package/dist/cjs/SqlJournal.d.ts +173 -0
- package/dist/cjs/SqlJournal.d.ts.map +1 -0
- package/dist/cjs/SqlJournal.js +1568 -0
- package/dist/cjs/SqlJournal.js.map +7 -0
- package/dist/cjs/StepFact.d.ts +66 -0
- package/dist/cjs/StepFact.d.ts.map +1 -0
- package/dist/cjs/StepFact.js +68 -0
- package/dist/cjs/StepFact.js.map +7 -0
- package/dist/cjs/index.d.ts +95 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +63 -0
- package/dist/cjs/index.js.map +7 -0
- package/dist/cjs/internal/JournalInternalFault.d.ts +37 -0
- package/dist/cjs/internal/JournalInternalFault.d.ts.map +1 -0
- package/dist/cjs/internal/JournalInternalFault.js +43 -0
- package/dist/cjs/internal/JournalInternalFault.js.map +7 -0
- package/dist/cjs/migrations/0001_initial.d.ts +15 -0
- package/dist/cjs/migrations/0001_initial.d.ts.map +1 -0
- package/dist/cjs/migrations/0001_initial.js +54 -0
- package/dist/cjs/migrations/0001_initial.js.map +7 -0
- package/dist/cjs/migrations/0002_checkpoints.d.ts +27 -0
- package/dist/cjs/migrations/0002_checkpoints.d.ts.map +1 -0
- package/dist/cjs/migrations/0002_checkpoints.js +48 -0
- package/dist/cjs/migrations/0002_checkpoints.js.map +7 -0
- package/dist/cjs/migrations/0003_startup_index.d.ts +15 -0
- package/dist/cjs/migrations/0003_startup_index.d.ts.map +1 -0
- package/dist/cjs/migrations/0003_startup_index.js +40 -0
- package/dist/cjs/migrations/0003_startup_index.js.map +7 -0
- package/dist/cjs/migrations/0004_dedup.d.ts +15 -0
- package/dist/cjs/migrations/0004_dedup.d.ts.map +1 -0
- package/dist/cjs/migrations/0004_dedup.js +57 -0
- package/dist/cjs/migrations/0004_dedup.js.map +7 -0
- package/dist/cjs/migrations/0005_run_event_type.d.ts +15 -0
- package/dist/cjs/migrations/0005_run_event_type.d.ts.map +1 -0
- package/dist/cjs/migrations/0005_run_event_type.js +40 -0
- package/dist/cjs/migrations/0005_run_event_type.js.map +7 -0
- package/dist/cjs/migrations/0006_consensus.d.ts +22 -0
- package/dist/cjs/migrations/0006_consensus.d.ts.map +1 -0
- package/dist/cjs/migrations/0006_consensus.js +84 -0
- package/dist/cjs/migrations/0006_consensus.js.map +7 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/test/Notifying.d.ts +65 -0
- package/dist/cjs/test/Notifying.d.ts.map +1 -0
- package/dist/cjs/test/Notifying.js +62 -0
- package/dist/cjs/test/Notifying.js.map +7 -0
- package/dist/cjs/test/TestJournal.d.ts +43 -0
- package/dist/cjs/test/TestJournal.d.ts.map +1 -0
- package/dist/cjs/test/TestJournal.js +43 -0
- package/dist/cjs/test/TestJournal.js.map +7 -0
- package/dist/esm/CallFact.d.ts +129 -0
- package/dist/esm/CallFact.d.ts.map +1 -0
- package/dist/esm/CallFact.js +96 -0
- package/dist/esm/CallFact.js.map +1 -0
- package/dist/esm/Consensus.d.ts +440 -0
- package/dist/esm/Consensus.d.ts.map +1 -0
- package/dist/esm/Consensus.js +454 -0
- package/dist/esm/Consensus.js.map +1 -0
- package/dist/esm/EngineEvent.d.ts +890 -0
- package/dist/esm/EngineEvent.d.ts.map +1 -0
- package/dist/esm/EngineEvent.js +614 -0
- package/dist/esm/EngineEvent.js.map +1 -0
- package/dist/esm/ExecutionFact.d.ts +216 -0
- package/dist/esm/ExecutionFact.d.ts.map +1 -0
- package/dist/esm/ExecutionFact.js +374 -0
- package/dist/esm/ExecutionFact.js.map +1 -0
- package/dist/esm/Journal.d.ts +617 -0
- package/dist/esm/Journal.d.ts.map +1 -0
- package/dist/esm/Journal.js +323 -0
- package/dist/esm/Journal.js.map +1 -0
- package/dist/esm/JournalEvent.d.ts +421 -0
- package/dist/esm/JournalEvent.d.ts.map +1 -0
- package/dist/esm/JournalEvent.js +517 -0
- package/dist/esm/JournalEvent.js.map +1 -0
- package/dist/esm/JournalGeneration.d.ts +34 -0
- package/dist/esm/JournalGeneration.d.ts.map +1 -0
- package/dist/esm/JournalGeneration.js +65 -0
- package/dist/esm/JournalGeneration.js.map +1 -0
- package/dist/esm/JournalMetrics.d.ts +72 -0
- package/dist/esm/JournalMetrics.d.ts.map +1 -0
- package/dist/esm/JournalMetrics.js +79 -0
- package/dist/esm/JournalMetrics.js.map +1 -0
- package/dist/esm/Migrations.d.ts +42 -0
- package/dist/esm/Migrations.d.ts.map +1 -0
- package/dist/esm/Migrations.js +59 -0
- package/dist/esm/Migrations.js.map +1 -0
- package/dist/esm/OwnerId.d.ts +40 -0
- package/dist/esm/OwnerId.d.ts.map +1 -0
- package/dist/esm/OwnerId.js +33 -0
- package/dist/esm/OwnerId.js.map +1 -0
- package/dist/esm/Projection.d.ts +29 -0
- package/dist/esm/Projection.d.ts.map +1 -0
- package/dist/esm/Projection.js +13 -0
- package/dist/esm/Projection.js.map +1 -0
- package/dist/esm/RedactedLogger.d.ts +121 -0
- package/dist/esm/RedactedLogger.d.ts.map +1 -0
- package/dist/esm/RedactedLogger.js +445 -0
- package/dist/esm/RedactedLogger.js.map +1 -0
- package/dist/esm/Redaction.d.ts +350 -0
- package/dist/esm/Redaction.d.ts.map +1 -0
- package/dist/esm/Redaction.js +1584 -0
- package/dist/esm/Redaction.js.map +1 -0
- package/dist/esm/SqlConsensus.d.ts +44 -0
- package/dist/esm/SqlConsensus.d.ts.map +1 -0
- package/dist/esm/SqlConsensus.js +252 -0
- package/dist/esm/SqlConsensus.js.map +1 -0
- package/dist/esm/SqlJournal.d.ts +173 -0
- package/dist/esm/SqlJournal.d.ts.map +1 -0
- package/dist/esm/SqlJournal.js +1858 -0
- package/dist/esm/SqlJournal.js.map +1 -0
- package/dist/esm/StepFact.d.ts +66 -0
- package/dist/esm/StepFact.d.ts.map +1 -0
- package/dist/esm/StepFact.js +50 -0
- package/dist/esm/StepFact.js.map +1 -0
- package/dist/esm/index.d.ts +95 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +95 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/internal/JournalInternalFault.d.ts +37 -0
- package/dist/esm/internal/JournalInternalFault.d.ts.map +1 -0
- package/dist/esm/internal/JournalInternalFault.js +28 -0
- package/dist/esm/internal/JournalInternalFault.js.map +1 -0
- package/dist/esm/migrations/0001_initial.d.ts +15 -0
- package/dist/esm/migrations/0001_initial.d.ts.map +1 -0
- package/dist/esm/migrations/0001_initial.js +32 -0
- package/dist/esm/migrations/0001_initial.js.map +1 -0
- package/dist/esm/migrations/0002_checkpoints.d.ts +27 -0
- package/dist/esm/migrations/0002_checkpoints.d.ts.map +1 -0
- package/dist/esm/migrations/0002_checkpoints.js +38 -0
- package/dist/esm/migrations/0002_checkpoints.js.map +1 -0
- package/dist/esm/migrations/0003_startup_index.d.ts +15 -0
- package/dist/esm/migrations/0003_startup_index.d.ts.map +1 -0
- package/dist/esm/migrations/0003_startup_index.js +18 -0
- package/dist/esm/migrations/0003_startup_index.js.map +1 -0
- package/dist/esm/migrations/0004_dedup.d.ts +15 -0
- package/dist/esm/migrations/0004_dedup.d.ts.map +1 -0
- package/dist/esm/migrations/0004_dedup.js +38 -0
- package/dist/esm/migrations/0004_dedup.js.map +1 -0
- package/dist/esm/migrations/0005_run_event_type.d.ts +15 -0
- package/dist/esm/migrations/0005_run_event_type.d.ts.map +1 -0
- package/dist/esm/migrations/0005_run_event_type.js +18 -0
- package/dist/esm/migrations/0005_run_event_type.js.map +1 -0
- package/dist/esm/migrations/0006_consensus.d.ts +22 -0
- package/dist/esm/migrations/0006_consensus.d.ts.map +1 -0
- package/dist/esm/migrations/0006_consensus.js +69 -0
- package/dist/esm/migrations/0006_consensus.js.map +1 -0
- package/dist/esm/test/Notifying.d.ts +65 -0
- package/dist/esm/test/Notifying.d.ts.map +1 -0
- package/dist/esm/test/Notifying.js +62 -0
- package/dist/esm/test/Notifying.js.map +1 -0
- package/dist/esm/test/TestJournal.d.ts +43 -0
- package/dist/esm/test/TestJournal.d.ts.map +1 -0
- package/dist/esm/test/TestJournal.js +27 -0
- package/dist/esm/test/TestJournal.js.map +1 -0
- package/docs/README.md +164 -0
- package/docs/api.md +639 -0
- package/docs/concepts/compaction.md +157 -0
- package/docs/concepts/idempotency.md +127 -0
- package/docs/concepts/owner-fence.md +124 -0
- package/docs/concepts/redaction.md +218 -0
- package/docs/concepts/state-event-authority.md +159 -0
- package/docs/concepts/two-channels.md +167 -0
- package/docs/guides/commit-state-and-entry.md +114 -0
- package/docs/guides/compact-a-run.md +134 -0
- package/docs/guides/fold-a-projection.md +106 -0
- package/docs/guides/read-a-run.md +139 -0
- package/docs/guides/redact-log-output.md +94 -0
- package/docs/guides/testing.md +124 -0
- package/docs/guides/write-lifecycle-events.md +110 -0
- package/docs/installation.md +133 -0
- package/docs/quickstart.md +143 -0
- package/docs/troubleshooting.md +214 -0
- package/package.json +263 -3
- package/src/CallFact.ts +117 -0
- package/src/Consensus.ts +683 -0
- package/src/EngineEvent.ts +823 -0
- package/src/ExecutionFact.ts +433 -0
- package/src/Journal.ts +688 -0
- package/src/JournalEvent.ts +654 -0
- package/src/JournalGeneration.ts +77 -0
- package/src/JournalMetrics.ts +89 -0
- package/src/Migrations.ts +62 -0
- package/src/OwnerId.ts +42 -0
- package/src/Projection.ts +31 -0
- package/src/RedactedLogger.ts +483 -0
- package/src/Redaction.ts +1784 -0
- package/src/SqlConsensus.ts +344 -0
- package/src/SqlJournal.ts +2732 -0
- package/src/StepFact.ts +69 -0
- package/src/index.ts +109 -0
- package/src/internal/JournalInternalFault.ts +40 -0
- package/src/migrations/0001_initial.ts +41 -0
- package/src/migrations/0002_checkpoints.ts +46 -0
- package/src/migrations/0003_startup_index.ts +19 -0
- package/src/migrations/0004_dedup.ts +43 -0
- package/src/migrations/0005_run_event_type.ts +19 -0
- package/src/migrations/0006_consensus.ts +83 -0
- package/src/test/Notifying.ts +101 -0
- package/src/test/TestJournal.ts +52 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# @smthrs/journal
|
|
2
|
+
|
|
3
|
+
## [Unreleased]
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- A lossy batch the writer fails to commit is logged and counted on the new
|
|
8
|
+
`flows_journal_lost` counter (`JournalMetrics.lostEntries`, `lost(code)`),
|
|
9
|
+
so telemetry lost with no `flush` caller is no longer silent. A final flush
|
|
10
|
+
that fails while the journal closes is logged instead of ignored.
|
|
11
|
+
- Migration `0003_startup_index` lives in `src/migrations/` beside the other
|
|
12
|
+
migrations instead of `src/internal/`.
|
|
13
|
+
|
|
14
|
+
- The migration modules `0001_initial` and `0002_checkpoints` export their
|
|
15
|
+
Effect as a named binding (`initial`, `checkpoints`) instead of a default
|
|
16
|
+
export, and `Migrations` imports them by name. The CommonJS build converts
|
|
17
|
+
each source file with esbuild in Node interop mode, where a default import
|
|
18
|
+
of a sibling module resolves to that module's whole exports object rather
|
|
19
|
+
than the Effect, so `Migrations.set.migrations["0001_initial"].pipe` was
|
|
20
|
+
undefined under `require` while the ESM build kept working.
|
|
21
|
+
|
|
22
|
+
## [1.0.0-rc.0] - 2026-08-31
|
|
23
|
+
|
|
24
|
+
### Breaking Changes
|
|
25
|
+
|
|
26
|
+
- The stores and `SqlJournal` now require Effect's `SqlClient` service plus
|
|
27
|
+
`DurableWriter` (the renamed `Database` service) instead of the bundled
|
|
28
|
+
`Database` service.
|
|
29
|
+
- `emitDurable`, `checkpoint`, and `compact` require a well-formed `OwnerId`.
|
|
30
|
+
An omitted, null, or malformed owner fails `invalid_event` instead of
|
|
31
|
+
silently selecting the unfenced write path. `emitDurableUnfenced` is the one
|
|
32
|
+
sanctioned ownerless admission.
|
|
33
|
+
- `JournalEvent.RunId`, `JournalEvent.SourceId`, and `Input.eventType` reject
|
|
34
|
+
the empty string and ill-formed UTF-16 at decode. SQLite binds a lone
|
|
35
|
+
surrogate as U+FFFD, so two distinct identifiers collapsed to one persisted
|
|
36
|
+
key and destroyed run isolation.
|
|
37
|
+
- `JournalEvent.RunId`, `JournalEvent.SourceId`, and `Input.eventType` are
|
|
38
|
+
limited to 1,024 UTF-16 code units. `Seq` and `SourceSeq` exclude
|
|
39
|
+
`Number.MAX_SAFE_INTEGER`, whose successor is not a distinct integer the
|
|
40
|
+
journal can allocate.
|
|
41
|
+
- `EntriesOptions.limit` and the `entries` service reject pages above 10,000
|
|
42
|
+
entries, which would otherwise be decoded into memory in full.
|
|
43
|
+
- `OwnerId.pid` is a non-negative integer. A fractional, `NaN`, or negative
|
|
44
|
+
pid used to degrade into `fence_lost`, which reads as "someone else owns
|
|
45
|
+
this run" and sends the caller hunting a race that never happened.
|
|
46
|
+
- Durable read failures report the new `read_failed` code instead of `unknown`,
|
|
47
|
+
which is now reserved for a genuinely unclassified journal defect.
|
|
48
|
+
- `payload` and `meta` are encoded with sorted object keys, so producer
|
|
49
|
+
idempotency compares JSON values rather than one serialization of them. The
|
|
50
|
+
sort runs over the ENCODED JSON, so the persisted bytes keep every
|
|
51
|
+
`JSON.stringify` semantic.
|
|
52
|
+
- `JournalEvent.Entry.eventType` uses the same bounded identifier as
|
|
53
|
+
`Input.eventType`. It was a bare `Schema.String`, so a consumer decoding a
|
|
54
|
+
committed row accepted event types no emit could have produced.
|
|
55
|
+
- Every identifier rejects NUL. SQLite's `length()` stops at the first one, so
|
|
56
|
+
the column's own non-empty check failed and the caller was told `sink_failed`
|
|
57
|
+
about an identifier it had just supplied.
|
|
58
|
+
- `entries`, `stream`, `checkpoint`, `latestCheckpoint`, and `compact` decode
|
|
59
|
+
the schemas this package publishes instead of hand-checking a subset of them.
|
|
60
|
+
A lone-surrogate run id was refused at `emit` and answered with an empty page
|
|
61
|
+
at `entries`.
|
|
62
|
+
|
|
63
|
+
### Added
|
|
64
|
+
|
|
65
|
+
- `emitDurableUnfenced`, `checkpoint`, `latestCheckpoint`, `compact`, the
|
|
66
|
+
`Checkpoint` and `Compacted` model, and `SqlJournal.CompactionPolicy` for
|
|
67
|
+
automatic threshold-driven checkpoint-and-compact.
|
|
68
|
+
- `SqlJournalOptions.sourceEventCache` bounds the in-process
|
|
69
|
+
producer-idempotency index, and `SqlJournalOptions.redact` chooses the
|
|
70
|
+
redactor applied at the single encode chokepoint.
|
|
71
|
+
- `TestJournalOptions` forwards `sourceEventCache`, `redact`, and `compaction`,
|
|
72
|
+
so the sanctioned test bundle can exercise every layer option.
|
|
73
|
+
- `SqlJournalOptions.maxEntryBytes` bounds one entry's encoded bytes. It is
|
|
74
|
+
unset by default: `capacity` bounds entry COUNT, so without it a handful of
|
|
75
|
+
multi-megabyte payloads is the memory bill.
|
|
76
|
+
- Package-owned documentation under `docs/`, generated into
|
|
77
|
+
`docs/pages/api/journal.md` by `scripts/docs.mjs` and drift-checked by the
|
|
78
|
+
`//packages/journal:docsPages` target.
|
|
79
|
+
|
|
80
|
+
### Fixed
|
|
81
|
+
|
|
82
|
+
- `Redaction.defaultRules` covers GitHub tokens, AWS access keys, Slack tokens,
|
|
83
|
+
Google API keys, URL passwords, quoted `KEY="value"` assignments, and
|
|
84
|
+
embedded JSON credential members. The bearer rule consumes the full RFC 6750
|
|
85
|
+
token alphabet instead of stopping at the first `+`, `/`, or `~`.
|
|
86
|
+
- `Redaction.redact` mirrors `JSON.stringify`'s `toJSON` step, so a `Date`
|
|
87
|
+
persists as its ISO string instead of `{}`. The canonical encoder now runs
|
|
88
|
+
after encoding rather than over the raw redactor output, so the same `Date`
|
|
89
|
+
survives `Redaction.makeNoop()` too, and a redactor returning a cycle fails
|
|
90
|
+
`invalid_event` instead of killing the emit with a defect.
|
|
91
|
+
- `Redaction.isSensitiveKey` recognises `credential`, `credentials`, `dsn`, the
|
|
92
|
+
connection-string family, a plural form of every name it knew, and a trailing
|
|
93
|
+
`key` word. The permanent journal redacted strictly less than the one-shot
|
|
94
|
+
`smithers bug` report, which inverted the risk.
|
|
95
|
+
- The redacting console redacts the label `count`, `countReset`, `time`, and
|
|
96
|
+
`timeEnd` print. All four were bound straight to the delegate as if they
|
|
97
|
+
carried no output, and `timeLog` already redacted its label, so a timer could
|
|
98
|
+
never be found again under the name it was registered with.
|
|
99
|
+
- The compaction policy's per-run counter is serialized. Two settlements that
|
|
100
|
+
overlapped both issued the seeding COUNT and the later reply overwrote the
|
|
101
|
+
newer count with a stale one, so ten committed events produced no compaction
|
|
102
|
+
at all.
|
|
103
|
+
- A `Rule` with `replace` omitted now replaces the whole match, as its JSDoc
|
|
104
|
+
always said. It used to emit `"123-45-678=[REDACTED]"` for a match containing
|
|
105
|
+
no `=`, leaking every character but the last.
|
|
106
|
+
- A non-global `Rule.pattern` redacts every match instead of only the first.
|
|
107
|
+
- `Redaction.redactJsonString` fails closed. It used to return the original
|
|
108
|
+
secret JSON when re-encoding the redacted value failed.
|
|
109
|
+
- A payload with a throwing getter, a hostile `Proxy`, or extreme nesting fails
|
|
110
|
+
the emit with a typed `invalid_event` instead of an unrecoverable defect that
|
|
111
|
+
tore down the enclosing `transact` transaction.
|
|
112
|
+
- `Journal.stream` emits its first entry after one page instead of
|
|
113
|
+
materializing a run's whole history first.
|
|
114
|
+
- A lossy entry admitted before a compaction can no longer land below the
|
|
115
|
+
committed compaction floor, where it was persisted and unreadable forever.
|
|
116
|
+
- Automatic compaction runs off the layer-wide allocation permit, so a slow
|
|
117
|
+
`CompactionPolicy.capture` no longer stalls emits on unrelated runs, and
|
|
118
|
+
`capture` is bounded by a timeout.
|
|
119
|
+
- `checkpoint`'s receipt is decoded from the bytes it persisted, so it agrees
|
|
120
|
+
with `latestCheckpoint` and no longer aliases the caller's mutable state.
|
|
121
|
+
- One conflicted lossy entry no longer destroys its whole persisted batch.
|
|
122
|
+
- Entries published to `changes` are frozen, so one subscriber cannot mutate
|
|
123
|
+
another subscriber's view.
|
|
124
|
+
- Module headers and the README cite pages that exist. `docs/specs/` was never
|
|
125
|
+
imported into this repository.
|
|
126
|
+
- The internal `@slop` review markers no longer ship in the published
|
|
127
|
+
declarations. Every export they marked now carries the prose that retires
|
|
128
|
+
them, so a consumer's editor hover shows the contract rather than a note to
|
|
129
|
+
ourselves.
|
|
130
|
+
|
|
131
|
+
## [0.1.0] - 2026-08-05
|
|
132
|
+
|
|
133
|
+
This release predates the storage split. The run, attempt, and cache stores and
|
|
134
|
+
the deferred/clock migration named below moved to `@smthrs/run-store`,
|
|
135
|
+
`@smthrs/step-cache`, and `@smthrs/engine-store`; this package's `0002`
|
|
136
|
+
migration creates `flows_journal_checkpoints`.
|
|
137
|
+
|
|
138
|
+
### Fixed
|
|
139
|
+
|
|
140
|
+
- Kept journal admission, JSON validation, persistence normalization, and
|
|
141
|
+
ownership heartbeat loss in typed Effect failure/interruption channels.
|
|
142
|
+
- Replaced structural `_tag` probing with Schema and Effect SQL error guards.
|
|
143
|
+
|
|
144
|
+
### Added
|
|
145
|
+
|
|
146
|
+
- Added the non-blocking journal, fenced run and attempt stores, run
|
|
147
|
+
coordinator, migrations, and content-addressed cache.
|
|
148
|
+
- Added migration 0002 for durable deferred completions and absolute clock
|
|
149
|
+
deadlines.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 William Cory and the Smithers Flows contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,207 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @smthrs/journal
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Release candidate scope, host requirements and compatibility review are defined in the [library support policy](https://github.com/smithersai/smithers/blob/main/RELEASE_SUPPORT.md).
|
|
4
|
+
|
|
5
|
+
This package declares `effect` as an exact
|
|
6
|
+
`4.0.0-rc.115` peer dependency. Keep the application on that version so
|
|
7
|
+
all Smithers packages share one Effect runtime.
|
|
8
|
+
|
|
9
|
+
**Documentation:** https://journal.smithers.sh
|
|
10
|
+
|
|
11
|
+
An append-only event history for [Effect](https://effect.website) applications.
|
|
12
|
+
`@smthrs/journal` records what a long-running piece of work did, in order, in
|
|
13
|
+
SQLite. Rows are appended and never updated, so the history reads the same on
|
|
14
|
+
the tenth pass as on the first, and a process that dies halfway through leaves
|
|
15
|
+
behind everything it had already committed.
|
|
16
|
+
|
|
17
|
+
It is a set of Effect services: every write returns a typed receipt or a typed
|
|
18
|
+
failure, and the database arrives as a layer you compose. It belongs to the
|
|
19
|
+
Smithers durable flow engine, but it runs on its own, and no other Smithers
|
|
20
|
+
package is required.
|
|
21
|
+
|
|
22
|
+
## Install
|
|
23
|
+
|
|
24
|
+
Not on npm yet; see [Installation](https://github.com/smithersai/smithers/blob/main/packages/smithers/flows/flow/docs/installation.md#use-the-libraries).
|
|
25
|
+
|
|
26
|
+
`effect` is a peer dependency at exactly `4.0.0-rc.115`. Two copies of `effect`
|
|
27
|
+
in one program are two sets of service tags, so a journal layer built against
|
|
28
|
+
one copy cannot be provided to a program holding the other.
|
|
29
|
+
|
|
30
|
+
Node.js 26.4.0 or later is required for the Node SQLite driver. The package
|
|
31
|
+
ships as both ESM and CommonJS with TypeScript declarations.
|
|
32
|
+
|
|
33
|
+
## Write one run and read it back
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
import * as DurableWriter from "@smthrs/database/DurableWriter"
|
|
37
|
+
import * as NodeDatabase from "@smthrs/database/node/NodeDatabase"
|
|
38
|
+
import { Journal, JournalEvent, Migrations, SqlJournal } from "@smthrs/journal"
|
|
39
|
+
import * as Effect from "effect/Effect"
|
|
40
|
+
import * as Layer from "effect/Layer"
|
|
41
|
+
|
|
42
|
+
const database = Layer.provideMerge(
|
|
43
|
+
DurableWriter.layer(),
|
|
44
|
+
NodeDatabase.layer({ filename: "history.db" })
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
const journalLayer = SqlJournal.layer({ capacity: 1024, overflow: "reject" }).pipe(
|
|
48
|
+
Layer.provide(Layer.provideMerge(Migrations.layer, database))
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
const runId = "run-1" as JournalEvent.RunId
|
|
52
|
+
const sourceId = "engine" as JournalEvent.SourceId
|
|
53
|
+
|
|
54
|
+
const program = Effect.gen(function*() {
|
|
55
|
+
const journal = yield* Journal.Journal
|
|
56
|
+
|
|
57
|
+
const created = yield* journal.emitDurableUnfenced({
|
|
58
|
+
runId,
|
|
59
|
+
sourceId,
|
|
60
|
+
eventType: "run.created",
|
|
61
|
+
payload: { flow: "build", token: "ghp_0123456789abcdefghijklmnopqrstuvwxyz" }
|
|
62
|
+
})
|
|
63
|
+
console.log("durable:", created._tag, "seq", created.seq)
|
|
64
|
+
|
|
65
|
+
yield* journal.emitLossy({
|
|
66
|
+
runId,
|
|
67
|
+
sourceId,
|
|
68
|
+
eventType: "step.progress",
|
|
69
|
+
payload: { step: "compile", percent: 40 }
|
|
70
|
+
})
|
|
71
|
+
yield* journal.flush
|
|
72
|
+
|
|
73
|
+
const page = yield* journal.entries({ runId, limit: 100 })
|
|
74
|
+
for (const entry of page.entries) {
|
|
75
|
+
console.log(entry.seq, entry.eventType, JSON.stringify(entry.payload))
|
|
76
|
+
}
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
await Effect.runPromise(program.pipe(Effect.provide(journalLayer), Effect.orDie))
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
```text
|
|
83
|
+
durable: Accepted seq 0
|
|
84
|
+
0 run.created {"flow":"build","token":"[REDACTED]"}
|
|
85
|
+
1 step.progress {"percent":40,"step":"compile"}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
The token came back as `[REDACTED]` because it was scrubbed before the row was
|
|
89
|
+
encoded, so the credential is not in `history.db` and never was. `SqlJournal.layer`
|
|
90
|
+
needs both database services: `SqlClient` to read through and `DurableWriter`
|
|
91
|
+
to write through.
|
|
92
|
+
|
|
93
|
+
## What the journal guarantees
|
|
94
|
+
|
|
95
|
+
- **Two channels, one order.** `emitDurable` and `emitDurableUnfenced` are on
|
|
96
|
+
disk before the call returns. `emitLossy` goes through a bounded queue that
|
|
97
|
+
drops under pressure rather than stalling the writer. Both land in one
|
|
98
|
+
per-run `seq`, so the cheap channel cannot reorder the expensive one.
|
|
99
|
+
- **Every write gets an answer.** An emission returns `Accepted`, `Duplicate`,
|
|
100
|
+
or `Dropped`, and every failure is a `JournalError` carrying one of fourteen
|
|
101
|
+
stable codes, from `invalid_event` and `fence_lost` through `queue_overflow`
|
|
102
|
+
and `sink_failed`.
|
|
103
|
+
- **A retry is not a second event.** Producer identity is
|
|
104
|
+
`(runId, sourceId, sourceSeq)`, unique in the database, so a producer that
|
|
105
|
+
replays after a crash gets `Duplicate` back rather than doubling its history.
|
|
106
|
+
- **Credentials never reach the file.** Payloads are scrubbed on the write
|
|
107
|
+
path, before encoding, because a row is permanent and gets replayed verbatim
|
|
108
|
+
to every later reader.
|
|
109
|
+
- **A stale process cannot append.** `emitDurable` takes an `OwnerId` and
|
|
110
|
+
commits only while the injected `Consensus` strategy still records that
|
|
111
|
+
owner as holding the run. A process that was replaced fails `fence_lost`
|
|
112
|
+
instead of writing into a history it no longer owns.
|
|
113
|
+
- **State and its entry commit together.** `transact` runs your own writes and
|
|
114
|
+
the entries describing them in one transaction and defers publication until
|
|
115
|
+
it commits, so the two can never disagree. Committing locally is not remote
|
|
116
|
+
atomicity: external effects still need idempotency keys, fencing tokens, or
|
|
117
|
+
compensation.
|
|
118
|
+
- **A long run stops growing.** A checkpoint pins replay state to a sequence,
|
|
119
|
+
and `compact` deletes the entries below it.
|
|
120
|
+
|
|
121
|
+
`Seq` is canonical per-run replay order; `SourceSeq` identifies producer
|
|
122
|
+
retries. Rejected and dropped admissions may consume either sequence, so gaps
|
|
123
|
+
are valid.
|
|
124
|
+
|
|
125
|
+
Post-commit compaction preserves the durable writer caller's Effect
|
|
126
|
+
interruption policy. Ordinary callers can interrupt a slow capture; a write
|
|
127
|
+
inside an uninterruptible cancellation finalizer keeps that policy, so
|
|
128
|
+
journaling cannot abandon the cleanup that follows the commit.
|
|
129
|
+
|
|
130
|
+
## Public API
|
|
131
|
+
|
|
132
|
+
The root exports each module as a namespace, and each is also importable from
|
|
133
|
+
the matching `@smthrs/journal/*` subpath. The
|
|
134
|
+
[API reference](https://journal.smithers.sh/reference/api/) lists every export
|
|
135
|
+
with its one-line summary.
|
|
136
|
+
|
|
137
|
+
| Namespace | What it holds |
|
|
138
|
+
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
139
|
+
| `Journal` | The service and its operations, the `Checkpoint` and `Compacted` models, typed errors, receipts, read options, constructors, and the no-op layer. |
|
|
140
|
+
| `JournalEvent` | Branded `RunId`, `Seq`, `SourceId`, and `SourceSeq`; the `Input` and committed `Entry` schemas; deterministic `makeEventId`. |
|
|
141
|
+
| `SqlJournal` | `SqlJournalOptions`, `CompactionPolicy`, the database-backed `layer(options)` fenced by `SqlConsensus`, and `layerWith(options)` over an injected strategy. |
|
|
142
|
+
| `OwnerId` | The fencing token `emitDurable` accepts, carrying `hostId`, `pid`, and `nonce`. |
|
|
143
|
+
| `Consensus` | The injectable ownership strategy: `claim`, `activate`, `heartbeat`, `reconfirm`, `release`, `steal`, `recover`, and the commit-time `guard`; typed outcomes; `LivenessEvidence`; the lease constants; `layerLocal`, `layerNoop`, `make`, `makeLocal`, `makeNoop`. |
|
|
144
|
+
| `SqlConsensus` | The default database-backed strategy over `flows_consensus_leases`: `make` and `layer`. |
|
|
145
|
+
| `Redaction` | The payload redaction applied to entries before they are written, its rule set, and `makeNoop`. |
|
|
146
|
+
| `Projection` | The reproducible `Projection` model and its identity constructor. |
|
|
147
|
+
| `JournalMetrics` | The `flows_journal_writes` counter and the per-channel views `SqlJournal` updates on every emission receipt. |
|
|
148
|
+
| `Migrations` | `set`, `run`, and `layer` for this package's tables: `flows_journal_events` with its indexes, `flows_journal_checkpoints`, `flows_journal_dedup`, and the `flows_consensus_leases` lease table. |
|
|
149
|
+
|
|
150
|
+
Two test entry points sit outside the root:
|
|
151
|
+
`@smthrs/journal/test/TestJournal` provides the production journal over an
|
|
152
|
+
in-memory database (Node only), and `@smthrs/journal/test/Notifying` wraps a
|
|
153
|
+
service so a hook fires around every operation, which is how you inject a crash
|
|
154
|
+
at an exact transition.
|
|
155
|
+
|
|
156
|
+
## What a fenced write needs
|
|
157
|
+
|
|
158
|
+
`emitDurable`, `checkpoint`, and `compact` gate their write on the
|
|
159
|
+
`Consensus` strategy the journal was built with: the write joins the
|
|
160
|
+
strategy's `guard` inside its own transaction and commits only while the
|
|
161
|
+
strategy still records the supplied owner as holding the run. `SqlJournal.layer`
|
|
162
|
+
fences through `SqlConsensus`, whose lease lives in `flows_consensus_leases`, a
|
|
163
|
+
table this package's own migrations create; `SqlJournal.layerWith` takes any
|
|
164
|
+
strategy, such as `Consensus.layerLocal` for a single process or the browser.
|
|
165
|
+
An owner takes the run through the strategy's `claim` and `activate`, which
|
|
166
|
+
[`@smthrs/run-store`](https://run-store.smithers.sh) drives for a durable run.
|
|
167
|
+
|
|
168
|
+
`emitDurableUnfenced` is the sanctioned path for a genuinely ownerless
|
|
169
|
+
admission, such as an import or a repair tool. Reaching for it to dodge
|
|
170
|
+
`fence_lost` writes exactly the zombie entry the fence exists to reject.
|
|
171
|
+
|
|
172
|
+
## Where the journal sits
|
|
173
|
+
|
|
174
|
+
The journal holds the history and nothing else. Run and attempt state live in
|
|
175
|
+
[`@smthrs/run-store`](https://run-store.smithers.sh), sealed step results in
|
|
176
|
+
[`@smthrs/step-cache`](https://step-cache.smithers.sh), and the durable
|
|
177
|
+
deferred and clock tables in
|
|
178
|
+
[`@smthrs/engine-store`](https://engine-store.smithers.sh). Those stores hold
|
|
179
|
+
the executable state, which is not derived from journal entries; `transact` is
|
|
180
|
+
what keeps the two halves consistent, because every one of them writes through
|
|
181
|
+
the same `DurableWriter`.
|
|
182
|
+
|
|
183
|
+
SQLite and PostgreSQL share this journal and migration ladder; see
|
|
184
|
+
[database configuration](../database/docs/concepts/sqlite-only.md).
|
|
185
|
+
|
|
186
|
+
Rewinding SQL histories expose `Journal.Service.generation(runId)`, which reads
|
|
187
|
+
`{ generation, afterSeq }` from `flows_journal_generations` (initially zero and
|
|
188
|
+
`-1`). The SQL layer installs this table idempotently on existing databases.
|
|
189
|
+
Time travel increments the generation in the archive transaction. Append-only
|
|
190
|
+
adapters may omit the operation; truncating adapters must implement it. The
|
|
191
|
+
`JournalGeneration.initialize` subpath shares the table installation with time
|
|
192
|
+
travel without adding a migration below an already applied migration block.
|
|
193
|
+
|
|
194
|
+
## Documentation
|
|
195
|
+
|
|
196
|
+
- [State and event authority](./docs/concepts/state-event-authority.md)
|
|
197
|
+
- [Installation](https://journal.smithers.sh/installation/)
|
|
198
|
+
- [Quickstart](https://journal.smithers.sh/quickstart/)
|
|
199
|
+
- [The two channels](https://journal.smithers.sh/concepts/two-channels/)
|
|
200
|
+
- [The owner fence](https://journal.smithers.sh/concepts/owner-fence/)
|
|
201
|
+
- [Checkpoints and compaction](https://journal.smithers.sh/concepts/compaction/)
|
|
202
|
+
- [API reference](https://journal.smithers.sh/reference/api/)
|
|
203
|
+
- [Troubleshooting](https://journal.smithers.sh/troubleshooting/)
|
|
204
|
+
|
|
205
|
+
## License
|
|
206
|
+
|
|
207
|
+
MIT
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Versioned facts for an authorized native cell invocation and its delivered result.
|
|
3
|
+
* @since 1.0.0
|
|
4
|
+
*/
|
|
5
|
+
import * as Context from "effect/Context";
|
|
6
|
+
import * as Schema from "effect/Schema";
|
|
7
|
+
/** Stable harness coordinates, independent of physical attempt or publication order.
|
|
8
|
+
* @category schemas
|
|
9
|
+
* @since 1.0.0
|
|
10
|
+
*/
|
|
11
|
+
export declare const Identity: Schema.Struct<{
|
|
12
|
+
/** Public logical run identity, not an authentication session credential. */
|
|
13
|
+
readonly runId: Schema.String;
|
|
14
|
+
readonly frame: Schema.Int;
|
|
15
|
+
readonly cell: Schema.String;
|
|
16
|
+
readonly ordinal: Schema.Int;
|
|
17
|
+
readonly declaration: Schema.String;
|
|
18
|
+
readonly layers: Schema.$Array<Schema.String>;
|
|
19
|
+
}>;
|
|
20
|
+
/** A call annotation contains data only and never changes an action key.
|
|
21
|
+
* @category schemas
|
|
22
|
+
* @since 1.0.0
|
|
23
|
+
*/
|
|
24
|
+
export declare const Call: Schema.Struct<{
|
|
25
|
+
readonly callId: Schema.String;
|
|
26
|
+
readonly identity: Schema.Struct<{
|
|
27
|
+
/** Public logical run identity, not an authentication session credential. */
|
|
28
|
+
readonly runId: Schema.String;
|
|
29
|
+
readonly frame: Schema.Int;
|
|
30
|
+
readonly cell: Schema.String;
|
|
31
|
+
readonly ordinal: Schema.Int;
|
|
32
|
+
readonly declaration: Schema.String;
|
|
33
|
+
readonly layers: Schema.$Array<Schema.String>;
|
|
34
|
+
}>;
|
|
35
|
+
readonly flowName: Schema.String;
|
|
36
|
+
readonly input: Schema.Codec<Schema.Json, Schema.Json, never, never>;
|
|
37
|
+
/**
|
|
38
|
+
* The resolved declaration's display projection, as its owner encoded it.
|
|
39
|
+
*
|
|
40
|
+
* JSON rather than a struct because the vocabulary belongs to
|
|
41
|
+
* `@smthrs/registry` (`Descriptor.FlowActivity`, `Descriptor.CallPresentation`),
|
|
42
|
+
* which sits above this package: `@smthrs/harness` `Cell.displayDescriptor`
|
|
43
|
+
* encodes it from a typed call and the reading card validates each field
|
|
44
|
+
* before it is displayed, so the journal carries it and claims nothing about
|
|
45
|
+
* it. Absent means the declaration claimed nothing.
|
|
46
|
+
*/
|
|
47
|
+
readonly descriptor: Schema.optional<Schema.Codec<Schema.Json, Schema.Json, never, never>>;
|
|
48
|
+
}>;
|
|
49
|
+
/** Decoded authorized call coordinates.
|
|
50
|
+
* @category models
|
|
51
|
+
* @since 1.0.0
|
|
52
|
+
*/
|
|
53
|
+
export type Call = typeof Call.Type;
|
|
54
|
+
declare const Annotation_base: Context.ServiceClass<Annotation, "@smthrs/journal/CallFact/Annotation", {
|
|
55
|
+
readonly phase: "invoked" | "settled";
|
|
56
|
+
readonly call: Call;
|
|
57
|
+
}>;
|
|
58
|
+
/** Native action annotation; only the existing controller record settles a call.
|
|
59
|
+
* @category services
|
|
60
|
+
* @since 1.0.0
|
|
61
|
+
*/
|
|
62
|
+
export declare class Annotation extends Annotation_base {
|
|
63
|
+
}
|
|
64
|
+
/** Public result vocabulary. Executable outcomes remain in the protected attempt row.
|
|
65
|
+
* @category schemas
|
|
66
|
+
* @since 1.0.0
|
|
67
|
+
*/
|
|
68
|
+
export declare const Result: Schema.Union<readonly [Schema.Struct<{
|
|
69
|
+
readonly outcome: Schema.Literal<"success">;
|
|
70
|
+
readonly value: Schema.Codec<Schema.Json, Schema.Json, never, never>;
|
|
71
|
+
readonly message: Schema.optional<Schema.String>;
|
|
72
|
+
readonly code: Schema.optionalKey<Schema.Never>;
|
|
73
|
+
}>, Schema.Struct<{
|
|
74
|
+
readonly outcome: Schema.Literal<"failure">;
|
|
75
|
+
readonly value: Schema.Codec<Schema.Json, Schema.Json, never, never>;
|
|
76
|
+
readonly message: Schema.optional<Schema.String>;
|
|
77
|
+
readonly code: Schema.optional<Schema.String>;
|
|
78
|
+
}>]>;
|
|
79
|
+
/** Bounded, redacted event projection; a truncation marker is still JSON.
|
|
80
|
+
* @category schemas
|
|
81
|
+
* @since 1.0.0
|
|
82
|
+
*/
|
|
83
|
+
export declare const Fact: Schema.Union<readonly [Schema.Struct<{
|
|
84
|
+
readonly phase: Schema.Literal<"invoked">;
|
|
85
|
+
readonly input: Schema.Codec<Schema.Json, Schema.Json, never, never>;
|
|
86
|
+
readonly descriptor: Schema.optional<Schema.Codec<Schema.Json, Schema.Json, never, never>>;
|
|
87
|
+
readonly version: Schema.Literal<1>;
|
|
88
|
+
readonly callId: Schema.String;
|
|
89
|
+
readonly identity: Schema.Struct<{
|
|
90
|
+
/** Public logical run identity, not an authentication session credential. */
|
|
91
|
+
readonly runId: Schema.String;
|
|
92
|
+
readonly frame: Schema.Int;
|
|
93
|
+
readonly cell: Schema.String;
|
|
94
|
+
readonly ordinal: Schema.Int;
|
|
95
|
+
readonly declaration: Schema.String;
|
|
96
|
+
readonly layers: Schema.$Array<Schema.String>;
|
|
97
|
+
}>;
|
|
98
|
+
readonly flowName: Schema.String;
|
|
99
|
+
}>, Schema.Struct<{
|
|
100
|
+
readonly phase: Schema.Literal<"settled">;
|
|
101
|
+
readonly outcome: Schema.Literals<readonly ["success", "failure"]>;
|
|
102
|
+
readonly value: Schema.Codec<Schema.Json, Schema.Json, never, never>;
|
|
103
|
+
readonly message: Schema.optional<Schema.Codec<Schema.Json, Schema.Json, never, never>>;
|
|
104
|
+
readonly code: Schema.optional<Schema.String>;
|
|
105
|
+
readonly version: Schema.Literal<1>;
|
|
106
|
+
readonly callId: Schema.String;
|
|
107
|
+
readonly identity: Schema.Struct<{
|
|
108
|
+
/** Public logical run identity, not an authentication session credential. */
|
|
109
|
+
readonly runId: Schema.String;
|
|
110
|
+
readonly frame: Schema.Int;
|
|
111
|
+
readonly cell: Schema.String;
|
|
112
|
+
readonly ordinal: Schema.Int;
|
|
113
|
+
readonly declaration: Schema.String;
|
|
114
|
+
readonly layers: Schema.$Array<Schema.String>;
|
|
115
|
+
}>;
|
|
116
|
+
readonly flowName: Schema.String;
|
|
117
|
+
}>]>;
|
|
118
|
+
/** Decoded public native call fact.
|
|
119
|
+
* @category models
|
|
120
|
+
* @since 1.0.0
|
|
121
|
+
*/
|
|
122
|
+
export type Fact = typeof Fact.Type;
|
|
123
|
+
/** The immutable native journal is the durable outbox consumed by the native bridge.
|
|
124
|
+
* @category events
|
|
125
|
+
* @since 1.0.0
|
|
126
|
+
*/
|
|
127
|
+
export declare const eventType = "flows.harness.call-fact.v1";
|
|
128
|
+
export {};
|
|
129
|
+
//# sourceMappingURL=CallFact.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CallFact.d.ts","sourceRoot":"","sources":["../../src/CallFact.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAA;AACzC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAEvC;;;GAGG;AACH,eAAO,MAAM,QAAQ;IACnB,6EAA6E;;;;;;;EAO7E,CAAA;AAEF;;;GAGG;AACH,eAAO,MAAM,IAAI;;;QAbf,6EAA6E;;;;;;;;;;IAkB7E;;;;;;;;;OASG;;EAEH,CAAA;AAEF;;;GAGG;AACH,MAAM,MAAM,IAAI,GAAG,OAAO,IAAI,CAAC,IAAI,CAAA;;oBAOjB,SAAS,GAAG,SAAS;mBACtB,IAAI;;AANrB;;;GAGG;AACH,qBAAa,UAAW,SAAQ,eAGW;CAAG;AAE9C;;;GAGG;AACH,eAAO,MAAM,MAAM;;;;;;;;;;IAajB,CAAA;AASF;;;GAGG;AACH,eAAO,MAAM,IAAI;;;;;;;QA5Ef,6EAA6E;;;;;;;;;;;;;;;;;;QAA7E,6EAA6E;;;;;;;;;IA2F7E,CAAA;AAEF;;;GAGG;AACH,MAAM,MAAM,IAAI,GAAG,OAAO,IAAI,CAAC,IAAI,CAAA;AAEnC;;;GAGG;AACH,eAAO,MAAM,SAAS,+BAA+B,CAAA"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var CallFact_exports = {};
|
|
30
|
+
__export(CallFact_exports, {
|
|
31
|
+
Annotation: () => Annotation,
|
|
32
|
+
Call: () => Call,
|
|
33
|
+
Fact: () => Fact,
|
|
34
|
+
Identity: () => Identity,
|
|
35
|
+
Result: () => Result,
|
|
36
|
+
eventType: () => eventType
|
|
37
|
+
});
|
|
38
|
+
module.exports = __toCommonJS(CallFact_exports);
|
|
39
|
+
var Context = __toESM(require("effect/Context"), 1);
|
|
40
|
+
var Schema = __toESM(require("effect/Schema"), 1);
|
|
41
|
+
const Identity = Schema.Struct({
|
|
42
|
+
/** Public logical run identity, not an authentication session credential. */
|
|
43
|
+
runId: Schema.String,
|
|
44
|
+
frame: Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)),
|
|
45
|
+
cell: Schema.String,
|
|
46
|
+
ordinal: Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)),
|
|
47
|
+
declaration: Schema.String,
|
|
48
|
+
layers: Schema.Array(Schema.String)
|
|
49
|
+
});
|
|
50
|
+
const Call = Schema.Struct({
|
|
51
|
+
callId: Schema.String.check(Schema.isPattern(/^cell-call-v1:[0-9a-f]{64}$/)),
|
|
52
|
+
identity: Identity,
|
|
53
|
+
flowName: Schema.String,
|
|
54
|
+
input: Schema.Json,
|
|
55
|
+
/**
|
|
56
|
+
* The resolved declaration's display projection, as its owner encoded it.
|
|
57
|
+
*
|
|
58
|
+
* JSON rather than a struct because the vocabulary belongs to
|
|
59
|
+
* `@smthrs/registry` (`Descriptor.FlowActivity`, `Descriptor.CallPresentation`),
|
|
60
|
+
* which sits above this package: `@smthrs/harness` `Cell.displayDescriptor`
|
|
61
|
+
* encodes it from a typed call and the reading card validates each field
|
|
62
|
+
* before it is displayed, so the journal carries it and claims nothing about
|
|
63
|
+
* it. Absent means the declaration claimed nothing.
|
|
64
|
+
*/
|
|
65
|
+
descriptor: Schema.optional(Schema.Json)
|
|
66
|
+
});
|
|
67
|
+
class Annotation extends Context.Service()("@smthrs/journal/CallFact/Annotation") {
|
|
68
|
+
}
|
|
69
|
+
const Result = Schema.Union([
|
|
70
|
+
Schema.Struct({
|
|
71
|
+
outcome: Schema.Literal("success"),
|
|
72
|
+
value: Schema.Json,
|
|
73
|
+
message: Schema.optional(Schema.String),
|
|
74
|
+
code: Schema.optionalKey(Schema.Never)
|
|
75
|
+
}),
|
|
76
|
+
Schema.Struct({
|
|
77
|
+
outcome: Schema.Literal("failure"),
|
|
78
|
+
value: Schema.Json,
|
|
79
|
+
message: Schema.optional(Schema.String),
|
|
80
|
+
code: Schema.optional(Schema.String)
|
|
81
|
+
})
|
|
82
|
+
]);
|
|
83
|
+
const coordinates = {
|
|
84
|
+
version: Schema.Literal(1),
|
|
85
|
+
callId: Call.fields.callId,
|
|
86
|
+
identity: Identity,
|
|
87
|
+
flowName: Schema.String
|
|
88
|
+
};
|
|
89
|
+
const Fact = Schema.Union([
|
|
90
|
+
Schema.Struct({
|
|
91
|
+
...coordinates,
|
|
92
|
+
phase: Schema.Literal("invoked"),
|
|
93
|
+
input: Schema.Json,
|
|
94
|
+
descriptor: Schema.optional(Schema.Json)
|
|
95
|
+
}),
|
|
96
|
+
Schema.Struct({
|
|
97
|
+
...coordinates,
|
|
98
|
+
phase: Schema.Literal("settled"),
|
|
99
|
+
outcome: Schema.Literals(["success", "failure"]),
|
|
100
|
+
value: Schema.Json,
|
|
101
|
+
message: Schema.optional(Schema.Json),
|
|
102
|
+
code: Schema.optional(Schema.String)
|
|
103
|
+
})
|
|
104
|
+
]);
|
|
105
|
+
const eventType = "flows.harness.call-fact.v1";
|
|
106
|
+
//# sourceMappingURL=CallFact.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/CallFact.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Versioned facts for an authorized native cell invocation and its delivered result.\n * @since 1.0.0\n */\n\nimport * as Context from \"effect/Context\"\nimport * as Schema from \"effect/Schema\"\n\n/** Stable harness coordinates, independent of physical attempt or publication order.\n * @category schemas\n * @since 1.0.0\n */\nexport const Identity = Schema.Struct({\n /** Public logical run identity, not an authentication session credential. */\n runId: Schema.String,\n frame: Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)),\n cell: Schema.String,\n ordinal: Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)),\n declaration: Schema.String,\n layers: Schema.Array(Schema.String)\n})\n\n/** A call annotation contains data only and never changes an action key.\n * @category schemas\n * @since 1.0.0\n */\nexport const Call = Schema.Struct({\n callId: Schema.String.check(Schema.isPattern(/^cell-call-v1:[0-9a-f]{64}$/)),\n identity: Identity,\n flowName: Schema.String,\n input: Schema.Json,\n /**\n * The resolved declaration's display projection, as its owner encoded it.\n *\n * JSON rather than a struct because the vocabulary belongs to\n * `@smthrs/registry` (`Descriptor.FlowActivity`, `Descriptor.CallPresentation`),\n * which sits above this package: `@smthrs/harness` `Cell.displayDescriptor`\n * encodes it from a typed call and the reading card validates each field\n * before it is displayed, so the journal carries it and claims nothing about\n * it. Absent means the declaration claimed nothing.\n */\n descriptor: Schema.optional(Schema.Json)\n})\n\n/** Decoded authorized call coordinates.\n * @category models\n * @since 1.0.0\n */\nexport type Call = typeof Call.Type\n\n/** Native action annotation; only the existing controller record settles a call.\n * @category services\n * @since 1.0.0\n */\nexport class Annotation extends Context.Service<Annotation, {\n readonly phase: \"invoked\" | \"settled\"\n readonly call: Call\n}>()(\"@smthrs/journal/CallFact/Annotation\") {}\n\n/** Public result vocabulary. Executable outcomes remain in the protected attempt row.\n * @category schemas\n * @since 1.0.0\n */\nexport const Result = Schema.Union([\n Schema.Struct({\n outcome: Schema.Literal(\"success\"),\n value: Schema.Json,\n message: Schema.optional(Schema.String),\n code: Schema.optionalKey(Schema.Never)\n }),\n Schema.Struct({\n outcome: Schema.Literal(\"failure\"),\n value: Schema.Json,\n message: Schema.optional(Schema.String),\n code: Schema.optional(Schema.String)\n })\n])\n\nconst coordinates = {\n version: Schema.Literal(1),\n callId: Call.fields.callId,\n identity: Identity,\n flowName: Schema.String\n}\n\n/** Bounded, redacted event projection; a truncation marker is still JSON.\n * @category schemas\n * @since 1.0.0\n */\nexport const Fact = Schema.Union([\n Schema.Struct({\n ...coordinates,\n phase: Schema.Literal(\"invoked\"),\n input: Schema.Json,\n descriptor: Schema.optional(Schema.Json)\n }),\n Schema.Struct({\n ...coordinates,\n phase: Schema.Literal(\"settled\"),\n outcome: Schema.Literals([\"success\", \"failure\"]),\n value: Schema.Json,\n message: Schema.optional(Schema.Json),\n code: Schema.optional(Schema.String)\n })\n])\n\n/** Decoded public native call fact.\n * @category models\n * @since 1.0.0\n */\nexport type Fact = typeof Fact.Type\n\n/** The immutable native journal is the durable outbox consumed by the native bridge.\n * @category events\n * @since 1.0.0\n */\nexport const eventType = \"flows.harness.call-fact.v1\"\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAKA,cAAyB;AACzB,aAAwB;AAMjB,MAAM,WAAW,OAAO,OAAO;AAAA;AAAA,EAEpC,OAAO,OAAO;AAAA,EACd,OAAO,OAAO,IAAI,MAAM,OAAO,uBAAuB,CAAC,CAAC;AAAA,EACxD,MAAM,OAAO;AAAA,EACb,SAAS,OAAO,IAAI,MAAM,OAAO,uBAAuB,CAAC,CAAC;AAAA,EAC1D,aAAa,OAAO;AAAA,EACpB,QAAQ,OAAO,MAAM,OAAO,MAAM;AACpC,CAAC;AAMM,MAAM,OAAO,OAAO,OAAO;AAAA,EAChC,QAAQ,OAAO,OAAO,MAAM,OAAO,UAAU,6BAA6B,CAAC;AAAA,EAC3E,UAAU;AAAA,EACV,UAAU,OAAO;AAAA,EACjB,OAAO,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWd,YAAY,OAAO,SAAS,OAAO,IAAI;AACzC,CAAC;AAYM,MAAM,mBAAmB,QAAQ,QAGrC,EAAE,qCAAqC,EAAE;AAAC;AAMtC,MAAM,SAAS,OAAO,MAAM;AAAA,EACjC,OAAO,OAAO;AAAA,IACZ,SAAS,OAAO,QAAQ,SAAS;AAAA,IACjC,OAAO,OAAO;AAAA,IACd,SAAS,OAAO,SAAS,OAAO,MAAM;AAAA,IACtC,MAAM,OAAO,YAAY,OAAO,KAAK;AAAA,EACvC,CAAC;AAAA,EACD,OAAO,OAAO;AAAA,IACZ,SAAS,OAAO,QAAQ,SAAS;AAAA,IACjC,OAAO,OAAO;AAAA,IACd,SAAS,OAAO,SAAS,OAAO,MAAM;AAAA,IACtC,MAAM,OAAO,SAAS,OAAO,MAAM;AAAA,EACrC,CAAC;AACH,CAAC;AAED,MAAM,cAAc;AAAA,EAClB,SAAS,OAAO,QAAQ,CAAC;AAAA,EACzB,QAAQ,KAAK,OAAO;AAAA,EACpB,UAAU;AAAA,EACV,UAAU,OAAO;AACnB;AAMO,MAAM,OAAO,OAAO,MAAM;AAAA,EAC/B,OAAO,OAAO;AAAA,IACZ,GAAG;AAAA,IACH,OAAO,OAAO,QAAQ,SAAS;AAAA,IAC/B,OAAO,OAAO;AAAA,IACd,YAAY,OAAO,SAAS,OAAO,IAAI;AAAA,EACzC,CAAC;AAAA,EACD,OAAO,OAAO;AAAA,IACZ,GAAG;AAAA,IACH,OAAO,OAAO,QAAQ,SAAS;AAAA,IAC/B,SAAS,OAAO,SAAS,CAAC,WAAW,SAAS,CAAC;AAAA,IAC/C,OAAO,OAAO;AAAA,IACd,SAAS,OAAO,SAAS,OAAO,IAAI;AAAA,IACpC,MAAM,OAAO,SAAS,OAAO,MAAM;AAAA,EACrC,CAAC;AACH,CAAC;AAYM,MAAM,YAAY;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|