@forgezero/runtime 0.1.6 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +834 -105
- package/dist/custody-share.js +12 -0
- package/dist/phrase.d.ts +1 -1
- package/package.json +260 -261
package/README.md
CHANGED
|
@@ -1,155 +1,884 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
GENERATED FILE — do not edit.
|
|
3
|
+
|
|
4
|
+
Change tools/generate-guides.ts or its typed sources, run `bun run guides`,
|
|
5
|
+
and commit the generator and rendered files together.
|
|
6
|
+
-->
|
|
7
|
+
|
|
1
8
|
# @forgezero/runtime
|
|
2
9
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
10
|
+
The machinery behind a request handler — jobs, queues, an outbox, a hash-chained audit trail, mail, backups, schema validation and exact money. 44 public modules, each imported on its own.
|
|
11
|
+
|
|
12
|
+
## Package overview
|
|
13
|
+
|
|
14
|
+
Anyone running a service, for the work that happens outside a request. Separate from `access` because a Cloudflare Worker wants the request pipeline and cannot run a backup job. Supported runtimes: bun, node. Package root: @forgezero/runtime. The sections below show the actual named imports emitted by each declaration entry point; wildcard imports are intentionally not used in the documentation.
|
|
7
15
|
|
|
8
|
-
|
|
9
|
-
|
|
16
|
+
```text
|
|
17
|
+
bun add @forgezero/runtime
|
|
18
|
+
```
|
|
10
19
|
|
|
11
|
-
|
|
20
|
+
## ForgeZero package family
|
|
21
|
+
|
|
22
|
+
The five packages are installation boundaries. Choose a package by who installs it; choose a subpath by the capability used in that file.
|
|
23
|
+
|
|
24
|
+
| package | short description | runtimes | documentation |
|
|
25
|
+
|---|---|---|---|
|
|
26
|
+
| @forgezero/vault | Scoped secret access with Agent, API-key and systemd-credential sources. | bun, node, workers, deno | [Open](https://www.forgezero.net/docs/vault-package) |
|
|
27
|
+
| @forgezero/access | Typed route, principal, factor, RBAC and request-pipeline contracts. | bun, node, workers, deno | [Open](https://www.forgezero.net/docs/access) |
|
|
28
|
+
| @forgezero/providers | Typed external providers with priority, health and classified fallback. | bun, node, workers, deno | [Open](https://www.forgezero.net/docs/providers) |
|
|
29
|
+
| @forgezero/runtime | Portable runtime primitives for queries, jobs, events, schemas and finance. | bun, node | [Open](https://www.forgezero.net/docs/runtime) |
|
|
30
|
+
| @forgezero/agent | Operator CLI and managed-node agent for bootstrap, deploy and lifecycle. | bun, node | [Open](https://www.forgezero.net/docs/agent) |
|
|
31
|
+
|
|
32
|
+
## @forgezero/runtime public imports and commands
|
|
33
|
+
|
|
34
|
+
Every row links to the detailed explanation and named-import/example area below. This table and those details are generated from the package inventory and emitted declarations.
|
|
35
|
+
|
|
36
|
+
| public entry | short description | runtime | details |
|
|
37
|
+
|---|---|---|---|
|
|
38
|
+
| @forgezero/runtime/query | Provider-neutral typed function contracts: decode untrusted input, run with caller-supplied services or storage, and strictly validate the result without coupling business logic to ForgeZero or ArangoDB. | portable | [Details + example](#forgezero-runtime-query) |
|
|
39
|
+
| @forgezero/runtime/jobs | Background work that never overlaps itself, advances a cursor only on success, and can be paused and inspected. | portable | [Details + example](#forgezero-runtime-jobs) |
|
|
40
|
+
| @forgezero/runtime/queue | Memory-only keyed work queue — awaited results, parallel across keys and strictly sequential within one; clustered callers atomically claim ownership in their own business store before submitting. | portable | [Details + example](#forgezero-runtime-queue) |
|
|
41
|
+
| @forgezero/runtime/outbox | Write the event with the record, deliver it after, in order per key with backoff and a dead-letter queue. | portable | [Details + example](#forgezero-runtime-outbox) |
|
|
42
|
+
| @forgezero/runtime/audit | Append-only records chained by hash, with a verifier that names the first altered entry. | portable | [Details + example](#forgezero-runtime-audit) |
|
|
43
|
+
| @forgezero/runtime/backup | Encrypted, chunked, verified snapshots to object storage — and the restore that reads them back. | portable | [Details + example](#forgezero-runtime-backup) |
|
|
44
|
+
| @forgezero/runtime/notify | Render a named template to text and HTML, escaped per part, refusing to send with a blank where a value should be. | portable | [Details + example](#forgezero-runtime-notify) |
|
|
45
|
+
| @forgezero/runtime/notify/templates | The six transactional messages ForgeZero sends. | portable | [Details + example](#forgezero-runtime-notify-templates) |
|
|
46
|
+
| @forgezero/runtime/calendar | Billing periods computed from an anchor, working days, holidays and due dates. | portable | [Details + example](#forgezero-runtime-calendar) |
|
|
47
|
+
| @forgezero/runtime/compliance | Screening as a decision record — tiers, rules and lists, failing closed when a list is unreachable. | portable | [Details + example](#forgezero-runtime-compliance) |
|
|
48
|
+
| @forgezero/runtime/totp | RFC 6238 TOTP on the existing HMAC — base32, an asymmetric window, and replay left to the caller. | portable | [Details + example](#forgezero-runtime-totp) |
|
|
49
|
+
| @forgezero/runtime/passkey | Passkeys for sites that are not us. A vault-held credential is as unphishable as one in a security chip provided the RP ID check never slips — `evil-example.com` ends with `example.com` and is a different site. | portable | [Details + example](#forgezero-runtime-passkey) |
|
|
50
|
+
| @forgezero/runtime/phrase | BIP-39 recovery phrases, and the salted verifier that proves one without being able to reconstruct it. | portable | [Details + example](#forgezero-runtime-phrase) |
|
|
51
|
+
| @forgezero/runtime/snp | Parse an AMD SEV-SNP attestation report at the firmware ABI offsets, and compare a TCB component by component so a microcode bump cannot mask a firmware downgrade. | portable | [Details + example](#forgezero-runtime-snp) |
|
|
52
|
+
| @forgezero/runtime/importers | Read secrets out of a .env, a CSV, or a Bitwarden or 1Password export — skipping what cannot be understood rather than guessing, and never putting a value in an error. | portable | [Details + example](#forgezero-runtime-importers) |
|
|
53
|
+
| @forgezero/runtime/openssh | OpenSSH wire encoding, so a derived ed25519 key becomes a line that pastes into authorized_keys. | portable | [Details + example](#forgezero-runtime-openssh) |
|
|
54
|
+
| @forgezero/runtime/ssh-cert | OpenSSH certificates, so access expires instead of having to be hunted down. Takes a signing FUNCTION rather than a secret key, which is what lets the CA live in a vault that never hands it out. | portable | [Details + example](#forgezero-runtime-ssh-cert) |
|
|
55
|
+
| @forgezero/runtime/slip10 | SLIP-0010 derivation for ed25519, hardened-only — BIP-32 does not work on this curve and produces halves that do not correspond. | portable | [Details + example](#forgezero-runtime-slip10) |
|
|
56
|
+
| @forgezero/runtime/identity | Hybrid Ed25519 + ML-DSA-65 request signing. One canonical string, so the compute agent that signs inside a guest and the API that verifies cannot drift — which two implementations of it certainly would. | portable | [Details + example](#forgezero-runtime-identity) |
|
|
57
|
+
| @forgezero/runtime/schema | Validate against JSON Schema, restrict what a caller may declare, and describe a schema as a form. | portable | [Details + example](#forgezero-runtime-schema) |
|
|
58
|
+
| @forgezero/runtime/schema/typebox | The TypeBox validator behind that interface. | portable | [Details + example](#forgezero-runtime-schema-typebox) |
|
|
59
|
+
| @forgezero/runtime/finance/discounts | Promotions as arithmetic over integer minor units. They never stack — one winner — and a percentage rounds down, because rounding a discount up gives away a unit of currency per invoice forever. | portable | [Details + example](#forgezero-runtime-finance-discounts) |
|
|
60
|
+
| @forgezero/runtime/finance/money | Exact amounts in minor units with the asset attached, so two currencies cannot be added. | portable | [Details + example](#forgezero-runtime-finance-money) |
|
|
61
|
+
| @forgezero/runtime/finance/venues | Trading venues, market types and symbols as data — spot, margin and futures behind one order model. | portable | [Details + example](#forgezero-runtime-finance-venues) |
|
|
62
|
+
| @forgezero/runtime/finance/ledger | Double-entry postings and derived balances. A hold is a posting, not a lock — the queue does the ordering. | portable | [Details + example](#forgezero-runtime-finance-ledger) |
|
|
63
|
+
| @forgezero/runtime/finance/commission | Profit net of flows, a high-water mark, the tier split and the referral share of our income. | portable | [Details + example](#forgezero-runtime-finance-commission) |
|
|
64
|
+
| @forgezero/runtime/finance/rates | What an asset is worth in USD, and how old that answer is. A peg never ages; a quote always does. | portable | [Details + example](#forgezero-runtime-finance-rates) |
|
|
65
|
+
| @forgezero/runtime/finance/transfers | Deposits and withdrawals as ordered pipelines, with screening reserved at position zero. | portable | [Details + example](#forgezero-runtime-finance-transfers) |
|
|
66
|
+
| @forgezero/runtime/finance/chain | Which chains exist, their confirmation depth by value band, assets and explorers — as data an admin edits. | portable | [Details + example](#forgezero-runtime-finance-chain) |
|
|
67
|
+
| @forgezero/runtime/finance/custody | Derive CREATE2 deposit addresses and EIP-712 custody digests — arithmetic over a seed and a salt, needing no credential and no node. | portable | [Details + example](#forgezero-runtime-finance-custody) |
|
|
68
|
+
| @forgezero/runtime/finance/derive | Declare a field ForgeZero generates rather than the tenant supplying: BIP-44 path arithmetic, and the choice of who is capable of generating the key. | portable | [Details + example](#forgezero-runtime-finance-derive) |
|
|
69
|
+
| @forgezero/runtime/finance/tax | Which jurisdiction may tax a sale, who accounts for it, and the three ways to be zero that report differently. Rates are data. | portable | [Details + example](#forgezero-runtime-finance-tax) |
|
|
70
|
+
| @forgezero/runtime/finance/storage | Write an amount so it is both exact and sortable: an authoritative string, and a number that is only an index. | portable | [Details + example](#forgezero-runtime-finance-storage) |
|
|
71
|
+
| @forgezero/runtime/realtime | Provider-neutral realtime audience, shard, event and delivery contracts. | portable | [Details + example](#forgezero-runtime-realtime) |
|
|
72
|
+
| @forgezero/runtime/passkey-hybrid | Versioned WebAuthn PRF plus ML-DSA companion proof construction and verification. | portable | [Details + example](#forgezero-runtime-passkey-hybrid) |
|
|
73
|
+
| @forgezero/runtime/otpauth | Parse and render otpauth URIs without binding enrolment to a UI framework. | portable | [Details + example](#forgezero-runtime-otpauth) |
|
|
74
|
+
| @forgezero/runtime/pipeline | Typed ordered application-pipeline execution with explicit evidence. | portable | [Details + example](#forgezero-runtime-pipeline) |
|
|
75
|
+
| @forgezero/runtime/finance/chain-addresses | Chain-address derivation records and validation independent of a node provider. | portable | [Details + example](#forgezero-runtime-finance-chain-addresses) |
|
|
76
|
+
| @forgezero/runtime/finance/chain-deposits | Provider-neutral deposit observation, confirmation and credit transitions. | portable | [Details + example](#forgezero-runtime-finance-chain-deposits) |
|
|
77
|
+
| @forgezero/runtime/finance/chain-withdrawals | Provider-neutral withdrawal approval, broadcast and finality transitions. | portable | [Details + example](#forgezero-runtime-finance-chain-withdrawals) |
|
|
78
|
+
| @forgezero/runtime/finance/chain-reconcile | Deterministic reconciliation between chain observations and durable transfer state. | portable | [Details + example](#forgezero-runtime-finance-chain-reconcile) |
|
|
79
|
+
| @forgezero/runtime/finance/market | Market order, fill and quote contracts independent of any exchange adapter. | portable | [Details + example](#forgezero-runtime-finance-market) |
|
|
80
|
+
| @forgezero/runtime/custody-share | Threshold-share parsing, validation and reconstruction. | portable | [Details + example](#forgezero-runtime-custody-share) |
|
|
81
|
+
| @forgezero/runtime/custody-crypto | Hybrid ML-KEM-768 plus X25519 custody-share sealing and opening. | portable | [Details + example](#forgezero-runtime-custody-crypto) |
|
|
82
|
+
|
|
83
|
+
## Commands
|
|
84
|
+
|
|
85
|
+
bun add @forgezero/runtime — Install runtime contracts; import the required subpath so unused capabilities stay out of the bundle.
|
|
86
|
+
|
|
87
|
+
```text
|
|
12
88
|
bun add @forgezero/runtime
|
|
13
89
|
```
|
|
14
90
|
|
|
15
|
-
|
|
91
|
+
<a id="forgezero-runtime-query"></a>
|
|
92
|
+
## @forgezero/runtime/query
|
|
93
|
+
|
|
94
|
+
Provider-neutral typed function contracts: decode untrusted input, run with caller-supplied services or storage, and strictly validate the result without coupling business logic to ForgeZero or ArangoDB. Named value imports: QueryContractError, defineQuery, implementQuery. Named type imports: QueryCodec, QueryContract, QueryDecode, QueryExecution, QueryImplementation, QueryInput, QueryIssue, QueryOutput. Import only the names used by this file.
|
|
95
|
+
|
|
96
|
+
```text
|
|
97
|
+
import { QueryContractError, defineQuery, implementQuery } from '@forgezero/runtime/query';
|
|
98
|
+
import type { QueryCodec, QueryContract, QueryDecode, QueryExecution, QueryImplementation, QueryInput } from '@forgezero/runtime/query';
|
|
99
|
+
import type { QueryIssue, QueryOutput } from '@forgezero/runtime/query';
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## @forgezero/runtime/query — Define and implement a typed query
|
|
103
|
+
|
|
104
|
+
Decode untrusted input and validate output around injected storage/services rather than embedding a database query in the route adapter.
|
|
105
|
+
|
|
106
|
+
```text
|
|
107
|
+
import { defineQuery, implementQuery } from '@forgezero/runtime/query';
|
|
108
|
+
import { T, type Static, typeboxQueryCodec } from '@forgezero/runtime/schema/typebox';
|
|
109
|
+
|
|
110
|
+
const OrderKey = T.Object({ orderKey: T.String({ minLength: 1 }) });
|
|
111
|
+
const Order = T.Object({ orderKey: T.String(), total: T.String() });
|
|
112
|
+
type OrderRow = Static<typeof Order>;
|
|
113
|
+
type Stores = { orders: { find(key: string): Promise<OrderRow | null> } };
|
|
114
|
+
declare const stores: Stores;
|
|
115
|
+
|
|
116
|
+
const findOrder = defineQuery({
|
|
117
|
+
name: 'orders.find',
|
|
118
|
+
input: typeboxQueryCodec(OrderKey),
|
|
119
|
+
output: typeboxQueryCodec(T.Union([Order, T.Null()]))
|
|
120
|
+
});
|
|
121
|
+
export const runFindOrder = implementQuery(findOrder,
|
|
122
|
+
(context: Stores, input) => context.orders.find(input.orderKey)
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
const order = await runFindOrder.execute(stores, { orderKey: 'ord_123' });
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
<a id="forgezero-runtime-jobs"></a>
|
|
129
|
+
## @forgezero/runtime/jobs
|
|
130
|
+
|
|
131
|
+
Background work that never overlaps itself, advances a cursor only on success, and can be paused and inspected. Named value imports: VERSION, createScheduler, cursorJob, defineJob, everyMs, memoryLock, nextWallClockAt, storeLock, systemClock. Named type imports: Clock, CursorBatch, CursorJobSpec, CursorStore, JobContext, JobLock, JobReport, JobResult, JobSpec, Lease, LockStore, Scheduler, SchedulerOptions, WallClockSchedule. Import only the names used by this file.
|
|
132
|
+
|
|
133
|
+
```text
|
|
134
|
+
import { VERSION, createScheduler, cursorJob, defineJob, everyMs, memoryLock } from '@forgezero/runtime/jobs';
|
|
135
|
+
import { nextWallClockAt, storeLock, systemClock } from '@forgezero/runtime/jobs';
|
|
136
|
+
import type { Clock, CursorBatch, CursorJobSpec, CursorStore, JobContext, JobLock } from '@forgezero/runtime/jobs';
|
|
137
|
+
import type { JobReport, JobResult, JobSpec, Lease, LockStore, Scheduler } from '@forgezero/runtime/jobs';
|
|
138
|
+
import type { SchedulerOptions, WallClockSchedule } from '@forgezero/runtime/jobs';
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
<a id="forgezero-runtime-queue"></a>
|
|
142
|
+
## @forgezero/runtime/queue
|
|
143
|
+
|
|
144
|
+
Memory-only keyed work queue — awaited results, parallel across keys and strictly sequential within one; clustered callers atomically claim ownership in their own business store before submitting. Named value imports: QueueKeyStoppedError, QueueStoppedError, TaskCancelledError, createQueue, queueWidthFor. Named type imports: DrainReport, Queue, QueueOptions, QueueResourcePolicy, QueueTask, RetryPolicy. Import only the names used by this file.
|
|
145
|
+
|
|
146
|
+
```text
|
|
147
|
+
import { QueueKeyStoppedError, QueueStoppedError, TaskCancelledError, createQueue, queueWidthFor } from '@forgezero/runtime/queue';
|
|
148
|
+
import type { DrainReport, Queue, QueueOptions, QueueResourcePolicy, QueueTask, RetryPolicy } from '@forgezero/runtime/queue';
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
<a id="forgezero-runtime-outbox"></a>
|
|
152
|
+
## @forgezero/runtime/outbox
|
|
153
|
+
|
|
154
|
+
Write the event with the record, deliver it after, in order per key with backoff and a dead-letter queue. Named value imports: DEFAULT_POLICY, EVENT_STATES, OutboxError, VERSION, backoffMs, createOutbox, memoryStore, outboxJob. Named type imports: DeliveryPolicy, DeliveryResult, DrainReport, EventState, Outbox, OutboxEvent, OutboxOptions, OutboxStore, PublishInput, Transport. Import only the names used by this file.
|
|
155
|
+
|
|
156
|
+
```text
|
|
157
|
+
import { DEFAULT_POLICY, EVENT_STATES, OutboxError, VERSION, backoffMs, createOutbox } from '@forgezero/runtime/outbox';
|
|
158
|
+
import { memoryStore, outboxJob } from '@forgezero/runtime/outbox';
|
|
159
|
+
import type { DeliveryPolicy, DeliveryResult, DrainReport, EventState, Outbox, OutboxEvent } from '@forgezero/runtime/outbox';
|
|
160
|
+
import type { OutboxOptions, OutboxStore, PublishInput, Transport } from '@forgezero/runtime/outbox';
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
<a id="forgezero-runtime-audit"></a>
|
|
164
|
+
## @forgezero/runtime/audit
|
|
165
|
+
|
|
166
|
+
Append-only records chained by hash, with a verifier that names the first altered entry. Named value imports: AuditChainError, GENESIS_DIGEST, VERSION, appendRecord, canonicalise, createAuditChain, exportRange, hashDigester, memoryStore, sealedDigester, verifyChain, verifyExport. Named type imports: AppendOptions, AuditChain, AuditChainOptions, AuditEntry, AuditExport, AuditRecord, AuditStore, ChainVerdict, Digester, EffectAuditRecord. Import only the names used by this file.
|
|
167
|
+
|
|
168
|
+
```text
|
|
169
|
+
import { AuditChainError, GENESIS_DIGEST, VERSION, appendRecord, canonicalise, createAuditChain } from '@forgezero/runtime/audit';
|
|
170
|
+
import { exportRange, hashDigester, memoryStore, sealedDigester, verifyChain, verifyExport } from '@forgezero/runtime/audit';
|
|
171
|
+
import type { AppendOptions, AuditChain, AuditChainOptions, AuditEntry, AuditExport, AuditRecord } from '@forgezero/runtime/audit';
|
|
172
|
+
import type { AuditStore, ChainVerdict, Digester, EffectAuditRecord } from '@forgezero/runtime/audit';
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
<a id="forgezero-runtime-backup"></a>
|
|
176
|
+
## @forgezero/runtime/backup
|
|
177
|
+
|
|
178
|
+
Encrypted, chunked, verified snapshots to object storage — and the restore that reads them back. Named value imports: BackupError, DEFAULT_RETENTION, SNAPSHOT_FORMAT, VERSION, backupJob, listSnapshots, prune, restore, selectForDeletion, snapshot, verifySnapshot. Named type imports: ChunkRecord, ObjectStore, RestoreOptions, RestoreReport, RetentionPolicy, RowSink, RowSource, SnapshotManifest, SnapshotOptions, VerifyReport. Import only the names used by this file.
|
|
179
|
+
|
|
180
|
+
```text
|
|
181
|
+
import { BackupError, DEFAULT_RETENTION, SNAPSHOT_FORMAT, VERSION, backupJob, listSnapshots } from '@forgezero/runtime/backup';
|
|
182
|
+
import { prune, restore, selectForDeletion, snapshot, verifySnapshot } from '@forgezero/runtime/backup';
|
|
183
|
+
import type { ChunkRecord, ObjectStore, RestoreOptions, RestoreReport, RetentionPolicy, RowSink } from '@forgezero/runtime/backup';
|
|
184
|
+
import type { RowSource, SnapshotManifest, SnapshotOptions, VerifyReport } from '@forgezero/runtime/backup';
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
<a id="forgezero-runtime-notify"></a>
|
|
188
|
+
## @forgezero/runtime/notify
|
|
189
|
+
|
|
190
|
+
Render a named template to text and HTML, escaped per part, refusing to send with a blank where a value should be. Named value imports: CHANNELS, NotifyError, VERSION, assertHeaderSafe, button, codeBlock, createNotifier, defineTemplate, escapeHtml, layout, preview, render. Named type imports: Channel, Notification, Notifier, NotifierOptions, Rendered, TemplateSpec, Transport. Import only the names used by this file.
|
|
191
|
+
|
|
192
|
+
```text
|
|
193
|
+
import { CHANNELS, NotifyError, VERSION, assertHeaderSafe, button, codeBlock } from '@forgezero/runtime/notify';
|
|
194
|
+
import { createNotifier, defineTemplate, escapeHtml, layout, preview, render } from '@forgezero/runtime/notify';
|
|
195
|
+
import type { Channel, Notification, Notifier, NotifierOptions, Rendered, TemplateSpec } from '@forgezero/runtime/notify';
|
|
196
|
+
import type { Transport } from '@forgezero/runtime/notify';
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
<a id="forgezero-runtime-notify-templates"></a>
|
|
200
|
+
## @forgezero/runtime/notify/templates
|
|
201
|
+
|
|
202
|
+
The six transactional messages ForgeZero sends. Named value imports: TEMPLATES, ceremonyProposed, custodianEnrolment, escapeHtml, invitation, newDevice, signInCode, vaultLocked. Named type imports: TemplateKey. Import only the names used by this file.
|
|
203
|
+
|
|
204
|
+
```text
|
|
205
|
+
import { TEMPLATES, ceremonyProposed, custodianEnrolment, escapeHtml, invitation, newDevice } from '@forgezero/runtime/notify/templates';
|
|
206
|
+
import { signInCode, vaultLocked } from '@forgezero/runtime/notify/templates';
|
|
207
|
+
import type { TemplateKey } from '@forgezero/runtime/notify/templates';
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
<a id="forgezero-runtime-calendar"></a>
|
|
211
|
+
## @forgezero/runtime/calendar
|
|
212
|
+
|
|
213
|
+
Billing periods computed from an anchor, working days, holidays and due dates. Named value imports: CalendarError, DAY_MS, DEFAULT_WORKING_DAYS, closedPeriods, dayOfWeek, daysOverdue, fromDay, isOverdue, isWorkingDay, nextWorkingDay, periodAt, periodIndexOn, periodOn, toDay, workingDaysBetween. Named type imports: BillingSchedule, Calendar, IsoDate, Period. Import only the names used by this file.
|
|
214
|
+
|
|
215
|
+
```text
|
|
216
|
+
import { CalendarError, DAY_MS, DEFAULT_WORKING_DAYS, closedPeriods, dayOfWeek, daysOverdue } from '@forgezero/runtime/calendar';
|
|
217
|
+
import { fromDay, isOverdue, isWorkingDay, nextWorkingDay, periodAt, periodIndexOn } from '@forgezero/runtime/calendar';
|
|
218
|
+
import { periodOn, toDay, workingDaysBetween } from '@forgezero/runtime/calendar';
|
|
219
|
+
import type { BillingSchedule, Calendar, IsoDate, Period } from '@forgezero/runtime/calendar';
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
<a id="forgezero-runtime-compliance"></a>
|
|
223
|
+
## @forgezero/runtime/compliance
|
|
224
|
+
|
|
225
|
+
Screening as a decision record — tiers, rules and lists, failing closed when a list is unreachable. Named value imports: ComplianceError, RISK_LEVELS, VERIFICATION_TIERS, combineLists, countryRule, newCounterpartyRule, screen, screeningStage, staticList, tierLimitRule, unavailableList. Named type imports: ListEntry, RiskLevel, Rule, RuleHit, ScreenOptions, ScreeningList, StageOptions, Subject, Verdict, VerificationTier. Import only the names used by this file.
|
|
226
|
+
|
|
227
|
+
```text
|
|
228
|
+
import { ComplianceError, RISK_LEVELS, VERIFICATION_TIERS, combineLists, countryRule, newCounterpartyRule } from '@forgezero/runtime/compliance';
|
|
229
|
+
import { screen, screeningStage, staticList, tierLimitRule, unavailableList } from '@forgezero/runtime/compliance';
|
|
230
|
+
import type { ListEntry, RiskLevel, Rule, RuleHit, ScreenOptions, ScreeningList } from '@forgezero/runtime/compliance';
|
|
231
|
+
import type { StageOptions, Subject, Verdict, VerificationTier } from '@forgezero/runtime/compliance';
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
<a id="forgezero-runtime-totp"></a>
|
|
235
|
+
## @forgezero/runtime/totp
|
|
236
|
+
|
|
237
|
+
RFC 6238 TOTP on the existing HMAC — base32, an asymmetric window, and replay left to the caller. Named value imports: DEFAULT_DIGITS, DEFAULT_STEP_SECONDS, TotpError, assertCode, codeAt, codeFor, counterAt, enrolmentUri, fromBase32, generateSecret, secondsRemaining, toBase32, verifyCode. Named type imports: TotpOptions, VerifyOptions, VerifyResult. Import only the names used by this file.
|
|
238
|
+
|
|
239
|
+
```text
|
|
240
|
+
import { DEFAULT_DIGITS, DEFAULT_STEP_SECONDS, TotpError, assertCode, codeAt, codeFor } from '@forgezero/runtime/totp';
|
|
241
|
+
import { counterAt, enrolmentUri, fromBase32, generateSecret, secondsRemaining, toBase32 } from '@forgezero/runtime/totp';
|
|
242
|
+
import { verifyCode } from '@forgezero/runtime/totp';
|
|
243
|
+
import type { TotpOptions, VerifyOptions, VerifyResult } from '@forgezero/runtime/totp';
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
<a id="forgezero-runtime-passkey"></a>
|
|
247
|
+
## @forgezero/runtime/passkey
|
|
248
|
+
|
|
249
|
+
Passkeys for sites that are not us. A vault-held credential is as unphishable as one in a security chip provided the RP ID check never slips — `evil-example.com` ends with `example.com` and is a different site. Named value imports: FLAG_BE, FLAG_BS, FLAG_UP, FLAG_UV, PasskeyError, assertPasskey, authenticatorData, credentialIdFor, passkeysFor, rpIdMatches, verifyAssertion. Named type imports: Assertion, AssertionRequest, StoredPasskey. Import only the names used by this file.
|
|
250
|
+
|
|
251
|
+
```text
|
|
252
|
+
import { FLAG_BE, FLAG_BS, FLAG_UP, FLAG_UV, PasskeyError, assertPasskey } from '@forgezero/runtime/passkey';
|
|
253
|
+
import { authenticatorData, credentialIdFor, passkeysFor, rpIdMatches, verifyAssertion } from '@forgezero/runtime/passkey';
|
|
254
|
+
import type { Assertion, AssertionRequest, StoredPasskey } from '@forgezero/runtime/passkey';
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
<a id="forgezero-runtime-phrase"></a>
|
|
258
|
+
## @forgezero/runtime/phrase
|
|
259
|
+
|
|
260
|
+
BIP-39 recovery phrases, and the salted verifier that proves one without being able to reconstruct it. Named value imports: PHRASE_SALT_BYTES, PHRASE_WORDS, generatePhrase, newSalt, phraseToKey, phraseVerifier, validatePhrase. Named type imports: none. Import only the names used by this file.
|
|
261
|
+
|
|
262
|
+
```text
|
|
263
|
+
import { PHRASE_SALT_BYTES, PHRASE_WORDS, generatePhrase, newSalt, phraseToKey, phraseVerifier } from '@forgezero/runtime/phrase';
|
|
264
|
+
import { validatePhrase } from '@forgezero/runtime/phrase';
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
<a id="forgezero-runtime-snp"></a>
|
|
268
|
+
## @forgezero/runtime/snp
|
|
269
|
+
|
|
270
|
+
Parse an AMD SEV-SNP attestation report at the firmware ABI offsets, and compare a TCB component by component so a microcode bump cannot mask a firmware downgrade. Named value imports: REPORT_BYTES, SnpError, bindsNonce, parseSnpReport, tcbAtLeast. Named type imports: GuestPolicy, SnpReport, TcbVersion. Import only the names used by this file.
|
|
271
|
+
|
|
272
|
+
```text
|
|
273
|
+
import { REPORT_BYTES, SnpError, bindsNonce, parseSnpReport, tcbAtLeast } from '@forgezero/runtime/snp';
|
|
274
|
+
import type { GuestPolicy, SnpReport, TcbVersion } from '@forgezero/runtime/snp';
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
<a id="forgezero-runtime-importers"></a>
|
|
278
|
+
## @forgezero/runtime/importers
|
|
279
|
+
|
|
280
|
+
Read secrets out of a .env, a CSV, or a Bitwarden or 1Password export — skipping what cannot be understood rather than guessing, and never putting a value in an error. Named value imports: IMPORT_FORMATS, normaliseName, parseBitwarden, parseCsv, parseEnv, parseImport, parseOnePassword. Named type imports: ImportFormat, ImportResult, ImportedSecret, Skipped. Import only the names used by this file.
|
|
281
|
+
|
|
282
|
+
```text
|
|
283
|
+
import { IMPORT_FORMATS, normaliseName, parseBitwarden, parseCsv, parseEnv, parseImport } from '@forgezero/runtime/importers';
|
|
284
|
+
import { parseOnePassword } from '@forgezero/runtime/importers';
|
|
285
|
+
import type { ImportFormat, ImportResult, ImportedSecret, Skipped } from '@forgezero/runtime/importers';
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
<a id="forgezero-runtime-openssh"></a>
|
|
289
|
+
## @forgezero/runtime/openssh
|
|
290
|
+
|
|
291
|
+
OpenSSH wire encoding, so a derived ed25519 key becomes a line that pastes into authorized_keys. Named value imports: OpenSshError, authorizedKey, fingerprint, parseAuthorizedKey, publicKeyBlob, signatureBlob. Named type imports: none. Import only the names used by this file.
|
|
292
|
+
|
|
293
|
+
```text
|
|
294
|
+
import { OpenSshError, authorizedKey, fingerprint, parseAuthorizedKey, publicKeyBlob, signatureBlob } from '@forgezero/runtime/openssh';
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
<a id="forgezero-runtime-ssh-cert"></a>
|
|
298
|
+
## @forgezero/runtime/ssh-cert
|
|
299
|
+
|
|
300
|
+
OpenSSH certificates, so access expires instead of having to be hunted down. Takes a signing FUNCTION rather than a secret key, which is what lets the CA live in a vault that never hands it out. Named value imports: CERT_TYPE_HOST, CERT_TYPE_USER, DEFAULT_EXTENSIONS, SshCertError, caFingerprint, caFromSecretKey, caPublicKeyLine, isCurrentlyValid, signCertificate. Named type imports: CertificateAuthority, CertificateRequest. Import only the names used by this file.
|
|
301
|
+
|
|
302
|
+
```text
|
|
303
|
+
import { CERT_TYPE_HOST, CERT_TYPE_USER, DEFAULT_EXTENSIONS, SshCertError, caFingerprint, caFromSecretKey } from '@forgezero/runtime/ssh-cert';
|
|
304
|
+
import { caPublicKeyLine, isCurrentlyValid, signCertificate } from '@forgezero/runtime/ssh-cert';
|
|
305
|
+
import type { CertificateAuthority, CertificateRequest } from '@forgezero/runtime/ssh-cert';
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
<a id="forgezero-runtime-slip10"></a>
|
|
309
|
+
## @forgezero/runtime/slip10
|
|
310
|
+
|
|
311
|
+
SLIP-0010 derivation for ed25519, hardened-only — BIP-32 does not work on this curve and produces halves that do not correspond. Named value imports: HARDENED_OFFSET, Slip10Error, deriveChild, derivePath, masterFromSeed. Named type imports: Slip10Node. Import only the names used by this file.
|
|
312
|
+
|
|
313
|
+
```text
|
|
314
|
+
import { HARDENED_OFFSET, Slip10Error, deriveChild, derivePath, masterFromSeed } from '@forgezero/runtime/slip10';
|
|
315
|
+
import type { Slip10Node } from '@forgezero/runtime/slip10';
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
<a id="forgezero-runtime-identity"></a>
|
|
319
|
+
## @forgezero/runtime/identity
|
|
320
|
+
|
|
321
|
+
Hybrid Ed25519 + ML-DSA-65 request signing. One canonical string, so the compute agent that signs inside a guest and the API that verifies cannot drift — which two implementations of it certainly would. Named value imports: CLOCK_SKEW_SECONDS, REQUEST_SIGNATURE_SUITE, RESPONSE_KEY_HEADER, RESPONSE_SEALING_SUITE, canonicalString, decodeSignatureHeader, deriveKeysFromSeed, derivePublicKeysFromSeed, encodeSignatureHeader, generateNodeKeys, generateResponseRecipient, openResponse, sealResponse, signRequest, validResponsePublicKey, verifyRequest. Named type imports: NodeKeyPair, NodePublicKeys, ResponseRecipient, SealedResponse, SignedEnvelope, VerifyFailure. Import only the names used by this file.
|
|
322
|
+
|
|
323
|
+
```text
|
|
324
|
+
import { CLOCK_SKEW_SECONDS, REQUEST_SIGNATURE_SUITE, RESPONSE_KEY_HEADER, RESPONSE_SEALING_SUITE, canonicalString, decodeSignatureHeader } from '@forgezero/runtime/identity';
|
|
325
|
+
import { deriveKeysFromSeed, derivePublicKeysFromSeed, encodeSignatureHeader, generateNodeKeys, generateResponseRecipient, openResponse } from '@forgezero/runtime/identity';
|
|
326
|
+
import { sealResponse, signRequest, validResponsePublicKey, verifyRequest } from '@forgezero/runtime/identity';
|
|
327
|
+
import type { NodeKeyPair, NodePublicKeys, ResponseRecipient, SealedResponse, SignedEnvelope, VerifyFailure } from '@forgezero/runtime/identity';
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
<a id="forgezero-runtime-schema"></a>
|
|
331
|
+
## @forgezero/runtime/schema
|
|
332
|
+
|
|
333
|
+
Validate against JSON Schema, restrict what a caller may declare, and describe a schema as a form. Named value imports: DEFAULT_RESTRICTIONS, SCHEMA_VERSION, SchemaError, VERSION, describeJsonSchema, readableFields, restrictJsonSchema, writeOnlyPaths. Named type imports: FieldKind, FormField, Restrictions, SchemaValidator, ValidationResult. Import only the names used by this file.
|
|
334
|
+
|
|
335
|
+
```text
|
|
336
|
+
import { DEFAULT_RESTRICTIONS, SCHEMA_VERSION, SchemaError, VERSION, describeJsonSchema, readableFields } from '@forgezero/runtime/schema';
|
|
337
|
+
import { restrictJsonSchema, writeOnlyPaths } from '@forgezero/runtime/schema';
|
|
338
|
+
import type { FieldKind, FormField, Restrictions, SchemaValidator, ValidationResult } from '@forgezero/runtime/schema';
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
## @forgezero/runtime/schema — Restrict an untrusted JSON Schema before storing it
|
|
342
|
+
|
|
343
|
+
Tenant-supplied schemas are data, not executable code. Restriction rejects references, remote identifiers, unsupported keywords, excessive depth/size, and arrays without a bounded maxItems. Form metadata is derived from the accepted schema; write-only fields remain identifiable for secret handling.
|
|
344
|
+
|
|
345
|
+
```text
|
|
346
|
+
import { restrictJsonSchema, describeJsonSchema, writeOnlyPaths } from '@forgezero/runtime/schema';
|
|
347
|
+
|
|
348
|
+
const schema = restrictJsonSchema({
|
|
349
|
+
type: 'object', additionalProperties: false,
|
|
350
|
+
properties: {
|
|
351
|
+
recipients: { type: 'array', maxItems: 100, items: { type: 'string' } },
|
|
352
|
+
apiKey: { type: 'string', title: 'API key', writeOnly: true }
|
|
353
|
+
},
|
|
354
|
+
required: ['apiKey']
|
|
355
|
+
});
|
|
356
|
+
const fields = describeJsonSchema(schema);
|
|
357
|
+
const secretFields = writeOnlyPaths(fields);
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
<a id="forgezero-runtime-schema-typebox"></a>
|
|
361
|
+
## @forgezero/runtime/schema/typebox
|
|
362
|
+
|
|
363
|
+
The TypeBox validator behind that interface. Named value imports: T, parse, typebox, typeboxQueryCodec. Named type imports: Static, TSchema. Import only the names used by this file.
|
|
364
|
+
|
|
365
|
+
```text
|
|
366
|
+
import { T, parse, typebox, typeboxQueryCodec } from '@forgezero/runtime/schema/typebox';
|
|
367
|
+
import type { Static, TSchema } from '@forgezero/runtime/schema/typebox';
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
## @forgezero/runtime/schema/typebox — One TypeBox shape for runtime validation and static types
|
|
371
|
+
|
|
372
|
+
TypeBox is an optional peer. Its schema is JSON Schema, so the same restriction and form layer applies. The query codec validates both untrusted input and returned output; malformed values fail instead of being coerced.
|
|
373
|
+
|
|
374
|
+
```text
|
|
375
|
+
import { T, type Static, parse, typeboxQueryCodec } from '@forgezero/runtime/schema/typebox';
|
|
376
|
+
|
|
377
|
+
const User = T.Object({
|
|
378
|
+
userKey: T.String({ minLength: 1 }),
|
|
379
|
+
roles: T.Array(T.String(), { maxItems: 32 })
|
|
380
|
+
}, { additionalProperties: false });
|
|
381
|
+
type User = Static<typeof User>;
|
|
382
|
+
const user: User = parse(User, unknownInput);
|
|
383
|
+
const codec = typeboxQueryCodec(User);
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
<a id="forgezero-runtime-finance-discounts"></a>
|
|
387
|
+
## @forgezero/runtime/finance/discounts
|
|
388
|
+
|
|
389
|
+
Promotions as arithmetic over integer minor units. They never stack — one winner — and a percentage rounds down, because rounding a discount up gives away a unit of currency per invoice forever. Named value imports: DiscountError, assertCode, assertWindow, bestDiscount, discountFor, ineligibility, normaliseCode. Named type imports: AppliedDiscount, DiscountKind, Ineligibility, Promotion. Import only the names used by this file.
|
|
390
|
+
|
|
391
|
+
```text
|
|
392
|
+
import { DiscountError, assertCode, assertWindow, bestDiscount, discountFor, ineligibility } from '@forgezero/runtime/finance/discounts';
|
|
393
|
+
import { normaliseCode } from '@forgezero/runtime/finance/discounts';
|
|
394
|
+
import type { AppliedDiscount, DiscountKind, Ineligibility, Promotion } from '@forgezero/runtime/finance/discounts';
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
<a id="forgezero-runtime-finance-money"></a>
|
|
398
|
+
## @forgezero/runtime/finance/money
|
|
399
|
+
|
|
400
|
+
Exact amounts in minor units with the asset attached, so two currencies cannot be added. Named value imports: ASSETS, MoneyError, ROUNDING, VERSION, abs, add, allocate, assetSpec, compare, convert, defineAsset, equals, formatAmount, isNegative, isZero, money, mulRate, negate, parseAmount, subtract, toStep, zero. Named type imports: AssetSpec, Money, Rounding. Import only the names used by this file.
|
|
401
|
+
|
|
402
|
+
```text
|
|
403
|
+
import { ASSETS, MoneyError, ROUNDING, VERSION, abs, add } from '@forgezero/runtime/finance/money';
|
|
404
|
+
import { allocate, assetSpec, compare, convert, defineAsset, equals } from '@forgezero/runtime/finance/money';
|
|
405
|
+
import { formatAmount, isNegative, isZero, money, mulRate, negate } from '@forgezero/runtime/finance/money';
|
|
406
|
+
import { parseAmount, subtract, toStep, zero } from '@forgezero/runtime/finance/money';
|
|
407
|
+
import type { AssetSpec, Money, Rounding } from '@forgezero/runtime/finance/money';
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
<a id="forgezero-runtime-finance-venues"></a>
|
|
411
|
+
## @forgezero/runtime/finance/venues
|
|
412
|
+
|
|
413
|
+
Trading venues, market types and symbols as data — spot, margin and futures behind one order model. Named value imports: MARKET_TYPES, ORDER_SIDES, ORDER_TYPES, TIME_IN_FORCE, VENUES, VERSION, VenueError, notionalOf, parseSymbol, submitOrder, symbolOf, validateOrder, venue, venuesFor. Named type imports: MarketSpec, MarketType, OrderRequest, OrderResult, OrderSide, OrderStatus, OrderType, TimeInForce, VenueAdapter, VenueSpec. Import only the names used by this file.
|
|
414
|
+
|
|
415
|
+
```text
|
|
416
|
+
import { MARKET_TYPES, ORDER_SIDES, ORDER_TYPES, TIME_IN_FORCE, VENUES, VERSION } from '@forgezero/runtime/finance/venues';
|
|
417
|
+
import { VenueError, notionalOf, parseSymbol, submitOrder, symbolOf, validateOrder } from '@forgezero/runtime/finance/venues';
|
|
418
|
+
import { venue, venuesFor } from '@forgezero/runtime/finance/venues';
|
|
419
|
+
import type { MarketSpec, MarketType, OrderRequest, OrderResult, OrderSide, OrderStatus } from '@forgezero/runtime/finance/venues';
|
|
420
|
+
import type { OrderType, TimeInForce, VenueAdapter, VenueSpec } from '@forgezero/runtime/finance/venues';
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
<a id="forgezero-runtime-finance-ledger"></a>
|
|
424
|
+
## @forgezero/runtime/finance/ledger
|
|
425
|
+
|
|
426
|
+
Double-entry postings and derived balances. A hold is a posting, not a lock — the queue does the ordering. Named value imports: ACCOUNT_KINDS, BUCKETS, LedgerError, MAX_LEDGER_ENTRIES, VERSION, accountId, assertAvailable, assertBalanced, availableOf, balanceOf, balancesFrom, captureHold, heldOf, parseAccount, placeHold, queueKeyFor, releaseHold, statement, totalOf, transfer, trialBalance. Named type imports: AccountKind, AccountRef, Bucket, Entry, Transaction, TrialBalance. Import only the names used by this file.
|
|
427
|
+
|
|
428
|
+
```text
|
|
429
|
+
import { ACCOUNT_KINDS, BUCKETS, LedgerError, MAX_LEDGER_ENTRIES, VERSION, accountId } from '@forgezero/runtime/finance/ledger';
|
|
430
|
+
import { assertAvailable, assertBalanced, availableOf, balanceOf, balancesFrom, captureHold } from '@forgezero/runtime/finance/ledger';
|
|
431
|
+
import { heldOf, parseAccount, placeHold, queueKeyFor, releaseHold, statement } from '@forgezero/runtime/finance/ledger';
|
|
432
|
+
import { totalOf, transfer, trialBalance } from '@forgezero/runtime/finance/ledger';
|
|
433
|
+
import type { AccountKind, AccountRef, Bucket, Entry, Transaction, TrialBalance } from '@forgezero/runtime/finance/ledger';
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
<a id="forgezero-runtime-finance-commission"></a>
|
|
437
|
+
## @forgezero/runtime/finance/commission
|
|
438
|
+
|
|
439
|
+
Profit net of flows, a high-water mark, the tier split and the referral share of our income. Named value imports: CommissionError, allocate, chargeableProfit, commissionTransaction, nextHighWaterMark, periodProfit, projectPrepay, splitCommission, splitReferrals. Named type imports: CommissionInput, CommissionSplit, PeriodPerformance, Prepay, PrepayInput, ReferralShare. Import only the names used by this file.
|
|
440
|
+
|
|
441
|
+
```text
|
|
442
|
+
import { CommissionError, allocate, chargeableProfit, commissionTransaction, nextHighWaterMark, periodProfit } from '@forgezero/runtime/finance/commission';
|
|
443
|
+
import { projectPrepay, splitCommission, splitReferrals } from '@forgezero/runtime/finance/commission';
|
|
444
|
+
import type { CommissionInput, CommissionSplit, PeriodPerformance, Prepay, PrepayInput, ReferralShare } from '@forgezero/runtime/finance/commission';
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
<a id="forgezero-runtime-finance-rates"></a>
|
|
448
|
+
## @forgezero/runtime/finance/rates
|
|
449
|
+
|
|
450
|
+
What an asset is worth in USD, and how old that answer is. A peg never ages; a quote always does. Named value imports: BASE_ASSET, RATE_SOURCES, RateError, assertRate, createRateTable, describeRate, isRegistered, peg, rateRefreshJob, refreshRates, registerAsset. Named type imports: AssetEntry, AssetRate, RateFetcher, RateSource, RateTable, RateTableOptions, RefreshReport. Import only the names used by this file.
|
|
451
|
+
|
|
452
|
+
```text
|
|
453
|
+
import { BASE_ASSET, RATE_SOURCES, RateError, assertRate, createRateTable, describeRate } from '@forgezero/runtime/finance/rates';
|
|
454
|
+
import { isRegistered, peg, rateRefreshJob, refreshRates, registerAsset } from '@forgezero/runtime/finance/rates';
|
|
455
|
+
import type { AssetEntry, AssetRate, RateFetcher, RateSource, RateTable, RateTableOptions } from '@forgezero/runtime/finance/rates';
|
|
456
|
+
import type { RefreshReport } from '@forgezero/runtime/finance/rates';
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
<a id="forgezero-runtime-finance-transfers"></a>
|
|
460
|
+
## @forgezero/runtime/finance/transfers
|
|
461
|
+
|
|
462
|
+
Deposits and withdrawals as ordered pipelines, with screening reserved at position zero. Named value imports: DIRECTIONS, PipelineError, SCREENING_ORDER, approvalStage, balanceStage, createTransferPipeline, limitsStage, notFrozenStage, screeningStage. Named type imports: Direction, PipelineResult, Stage, StageOutcome, Transfer, TransferPipeline. Import only the names used by this file.
|
|
463
|
+
|
|
464
|
+
```text
|
|
465
|
+
import { DIRECTIONS, PipelineError, SCREENING_ORDER, approvalStage, balanceStage, createTransferPipeline } from '@forgezero/runtime/finance/transfers';
|
|
466
|
+
import { limitsStage, notFrozenStage, screeningStage } from '@forgezero/runtime/finance/transfers';
|
|
467
|
+
import type { Direction, PipelineResult, Stage, StageOutcome, Transfer, TransferPipeline } from '@forgezero/runtime/finance/transfers';
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
<a id="forgezero-runtime-finance-chain"></a>
|
|
471
|
+
## @forgezero/runtime/finance/chain
|
|
472
|
+
|
|
473
|
+
Which chains exist, their confirmation depth by value band, assets and explorers — as data an admin edits. Named value imports: ADDRESS_SCHEMES, ChainError, SEED_CHAINS, SEED_CHAIN_ASSETS, assertChain, confirmationsFor, createChainRegistry, estimatedSeconds, validateAddress. Named type imports: AddressScheme, ChainAsset, ChainRegistry, ChainSpec, ConfirmationBand. Import only the names used by this file.
|
|
474
|
+
|
|
475
|
+
```text
|
|
476
|
+
import { ADDRESS_SCHEMES, ChainError, SEED_CHAINS, SEED_CHAIN_ASSETS, assertChain, confirmationsFor } from '@forgezero/runtime/finance/chain';
|
|
477
|
+
import { createChainRegistry, estimatedSeconds, validateAddress } from '@forgezero/runtime/finance/chain';
|
|
478
|
+
import type { AddressScheme, ChainAsset, ChainRegistry, ChainSpec, ConfirmationBand } from '@forgezero/runtime/finance/chain';
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
<a id="forgezero-runtime-finance-custody"></a>
|
|
482
|
+
## @forgezero/runtime/finance/custody
|
|
483
|
+
|
|
484
|
+
Derive CREATE2 deposit addresses and EIP-712 custody digests — arithmetic over a seed and a salt, needing no credential and no node. Named value imports: CustodyError, VERSION, depositAddress, domainSeparator, orderSignatures, saltFor, toChecksumAddress, withdrawDigest. Named type imports: none. Import only the names used by this file.
|
|
485
|
+
|
|
486
|
+
```text
|
|
487
|
+
import { CustodyError, VERSION, depositAddress, domainSeparator, orderSignatures, saltFor } from '@forgezero/runtime/finance/custody';
|
|
488
|
+
import { toChecksumAddress, withdrawDigest } from '@forgezero/runtime/finance/custody';
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
<a id="forgezero-runtime-finance-derive"></a>
|
|
492
|
+
## @forgezero/runtime/finance/derive
|
|
493
|
+
|
|
494
|
+
Declare a field ForgeZero generates rather than the tenant supplying: BIP-44 path arithmetic, and the choice of who is capable of generating the key. Named value imports: CUSTODY, DERIVE_KEYWORD, DeriveError, SCHEMES, assertDeriveSpec, custodyOf, deriveSpecOf, derivedFields, derivedPaths, pathFor, suppliedPaths. Named type imports: Custody, DeriveSpec, DerivedField, Scheme. Import only the names used by this file.
|
|
495
|
+
|
|
496
|
+
```text
|
|
497
|
+
import { CUSTODY, DERIVE_KEYWORD, DeriveError, SCHEMES, assertDeriveSpec, custodyOf } from '@forgezero/runtime/finance/derive';
|
|
498
|
+
import { deriveSpecOf, derivedFields, derivedPaths, pathFor, suppliedPaths } from '@forgezero/runtime/finance/derive';
|
|
499
|
+
import type { Custody, DeriveSpec, DerivedField, Scheme } from '@forgezero/runtime/finance/derive';
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
<a id="forgezero-runtime-finance-tax"></a>
|
|
503
|
+
## @forgezero/runtime/finance/tax
|
|
504
|
+
|
|
505
|
+
Which jurisdiction may tax a sale, who accounts for it, and the three ways to be zero that report differently. Rates are data. Named value imports: TREATMENTS, TaxError, applyTax, assertTaxRate, decideTax, describeTax, parseRate, percent, totalWithTax. Named type imports: Customer, Supplier, TaxAmounts, TaxDecision, TaxRate, Treatment. Import only the names used by this file.
|
|
506
|
+
|
|
507
|
+
```text
|
|
508
|
+
import { TREATMENTS, TaxError, applyTax, assertTaxRate, decideTax, describeTax } from '@forgezero/runtime/finance/tax';
|
|
509
|
+
import { parseRate, percent, totalWithTax } from '@forgezero/runtime/finance/tax';
|
|
510
|
+
import type { Customer, Supplier, TaxAmounts, TaxDecision, TaxRate, Treatment } from '@forgezero/runtime/finance/tax';
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
<a id="forgezero-runtime-finance-storage"></a>
|
|
514
|
+
## @forgezero/runtime/finance/storage
|
|
515
|
+
|
|
516
|
+
Write an amount so it is both exact and sortable: an authoritative string, and a number that is only an index. Named value imports: SORT_FIELD, fromStored, rangeBounds, sortExact, sortKey, storeAmount, toStored, withinRange. Named type imports: StoredMoney. Import only the names used by this file.
|
|
517
|
+
|
|
518
|
+
```text
|
|
519
|
+
import { SORT_FIELD, fromStored, rangeBounds, sortExact, sortKey, storeAmount } from '@forgezero/runtime/finance/storage';
|
|
520
|
+
import { toStored, withinRange } from '@forgezero/runtime/finance/storage';
|
|
521
|
+
import type { StoredMoney } from '@forgezero/runtime/finance/storage';
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
<a id="forgezero-runtime-realtime"></a>
|
|
525
|
+
## @forgezero/runtime/realtime
|
|
526
|
+
|
|
527
|
+
Provider-neutral realtime audience, shard, event and delivery contracts. Named value imports: REALTIME_MAX_BATCH_BYTES, REALTIME_MAX_EVENTS, REALTIME_MAX_EVENT_BYTES, REALTIME_MAX_SHARDS_PER_TOPIC, REALTIME_MAX_SOCKETS_PER_SHARD, canReceiveRealtimeAudience, issueRealtimeSubscriptionTicket, realtimeBatchBytes, realtimeHmac, realtimeShardKey, validateRealtimeAudience, validateRealtimeBatch, validateRealtimeSubscriptionTicket, verifyRealtimeHmac, verifyRealtimeSubscriptionToken. Named type imports: RealtimeAudience, RealtimeBatch, RealtimeEvent, RealtimePrincipalKind, RealtimeSubscriptionTicket. Import only the names used by this file.
|
|
528
|
+
|
|
529
|
+
```text
|
|
530
|
+
import { REALTIME_MAX_BATCH_BYTES, REALTIME_MAX_EVENTS, REALTIME_MAX_EVENT_BYTES, REALTIME_MAX_SHARDS_PER_TOPIC, REALTIME_MAX_SOCKETS_PER_SHARD, canReceiveRealtimeAudience } from '@forgezero/runtime/realtime';
|
|
531
|
+
import { issueRealtimeSubscriptionTicket, realtimeBatchBytes, realtimeHmac, realtimeShardKey, validateRealtimeAudience, validateRealtimeBatch } from '@forgezero/runtime/realtime';
|
|
532
|
+
import { validateRealtimeSubscriptionTicket, verifyRealtimeHmac, verifyRealtimeSubscriptionToken } from '@forgezero/runtime/realtime';
|
|
533
|
+
import type { RealtimeAudience, RealtimeBatch, RealtimeEvent, RealtimePrincipalKind, RealtimeSubscriptionTicket } from '@forgezero/runtime/realtime';
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
<a id="forgezero-runtime-passkey-hybrid"></a>
|
|
537
|
+
## @forgezero/runtime/passkey-hybrid
|
|
538
|
+
|
|
539
|
+
Versioned WebAuthn PRF plus ML-DSA companion proof construction and verification. Named value imports: PASSKEY_HYBRID_SUITE, PASSKEY_HYBRID_VERSION, PASSKEY_ML_DSA_PUBLIC_KEY_BYTES, PASSKEY_ML_DSA_SIGNATURE_BYTES, PASSKEY_PRF_SALT, createPasskeyHybridProof, passkeyHybridMessage, verifyPasskeyHybridProof. Named type imports: PasskeyHybridBinding, PasskeyHybridProof, PasskeyHybridPurpose, PasskeyHybridRegistrationProof. Import only the names used by this file.
|
|
540
|
+
|
|
541
|
+
```text
|
|
542
|
+
import { PASSKEY_HYBRID_SUITE, PASSKEY_HYBRID_VERSION, PASSKEY_ML_DSA_PUBLIC_KEY_BYTES, PASSKEY_ML_DSA_SIGNATURE_BYTES, PASSKEY_PRF_SALT, createPasskeyHybridProof } from '@forgezero/runtime/passkey-hybrid';
|
|
543
|
+
import { passkeyHybridMessage, verifyPasskeyHybridProof } from '@forgezero/runtime/passkey-hybrid';
|
|
544
|
+
import type { PasskeyHybridBinding, PasskeyHybridProof, PasskeyHybridPurpose, PasskeyHybridRegistrationProof } from '@forgezero/runtime/passkey-hybrid';
|
|
545
|
+
```
|
|
546
|
+
|
|
547
|
+
<a id="forgezero-runtime-otpauth"></a>
|
|
548
|
+
## @forgezero/runtime/otpauth
|
|
549
|
+
|
|
550
|
+
Parse and render otpauth URIs without binding enrolment to a UI framework. Named value imports: formatOtpAuth, fromManualSecret, newOtpAuth, parseOtpAuth. Named type imports: OtpAuth. Import only the names used by this file.
|
|
551
|
+
|
|
552
|
+
```text
|
|
553
|
+
import { formatOtpAuth, fromManualSecret, newOtpAuth, parseOtpAuth } from '@forgezero/runtime/otpauth';
|
|
554
|
+
import type { OtpAuth } from '@forgezero/runtime/otpauth';
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
<a id="forgezero-runtime-pipeline"></a>
|
|
558
|
+
## @forgezero/runtime/pipeline
|
|
559
|
+
|
|
560
|
+
Typed ordered application-pipeline execution with explicit evidence. Named value imports: GIT_PROVIDERS, PipelineError, parsePush, shouldDeploy, verifyWebhook, webhookPath. Named type imports: DeployTrigger, GitProvider, PushEvent. Import only the names used by this file.
|
|
561
|
+
|
|
562
|
+
```text
|
|
563
|
+
import { GIT_PROVIDERS, PipelineError, parsePush, shouldDeploy, verifyWebhook, webhookPath } from '@forgezero/runtime/pipeline';
|
|
564
|
+
import type { DeployTrigger, GitProvider, PushEvent } from '@forgezero/runtime/pipeline';
|
|
565
|
+
```
|
|
566
|
+
|
|
567
|
+
<a id="forgezero-runtime-finance-chain-addresses"></a>
|
|
568
|
+
## @forgezero/runtime/finance/chain-addresses
|
|
569
|
+
|
|
570
|
+
Chain-address derivation records and validation independent of a node provider. Named value imports: AddressError, COUNTERFACTUAL_SCHEMES, assertDerivationMatches, create2Address, depositAddressBook, depositSaltFor, deriveDepositAddress, ownerOfAddress, toChecksumAddress, validateAddress. Named type imports: AddressScheme, ChainDeployment. Import only the names used by this file.
|
|
571
|
+
|
|
572
|
+
```text
|
|
573
|
+
import { AddressError, COUNTERFACTUAL_SCHEMES, assertDerivationMatches, create2Address, depositAddressBook, depositSaltFor } from '@forgezero/runtime/finance/chain-addresses';
|
|
574
|
+
import { deriveDepositAddress, ownerOfAddress, toChecksumAddress, validateAddress } from '@forgezero/runtime/finance/chain-addresses';
|
|
575
|
+
import type { AddressScheme, ChainDeployment } from '@forgezero/runtime/finance/chain-addresses';
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
<a id="forgezero-runtime-finance-chain-deposits"></a>
|
|
579
|
+
## @forgezero/runtime/finance/chain-deposits
|
|
580
|
+
|
|
581
|
+
Provider-neutral deposit observation, confirmation and credit transitions. Named value imports: DepositError, creditDeposit, cursorFrom, depositReference, describeScan, isConfirmed, rescanRange, scanOnce. Named type imports: ChainReader, ChainTransfer, DepositCursor, ScanContext, ScanReport. Import only the names used by this file.
|
|
582
|
+
|
|
583
|
+
```text
|
|
584
|
+
import { DepositError, creditDeposit, cursorFrom, depositReference, describeScan, isConfirmed } from '@forgezero/runtime/finance/chain-deposits';
|
|
585
|
+
import { rescanRange, scanOnce } from '@forgezero/runtime/finance/chain-deposits';
|
|
586
|
+
import type { ChainReader, ChainTransfer, DepositCursor, ScanContext, ScanReport } from '@forgezero/runtime/finance/chain-deposits';
|
|
587
|
+
```
|
|
588
|
+
|
|
589
|
+
<a id="forgezero-runtime-finance-chain-withdrawals"></a>
|
|
590
|
+
## @forgezero/runtime/finance/chain-withdrawals
|
|
591
|
+
|
|
592
|
+
Provider-neutral withdrawal approval, broadcast and finality transitions. Named value imports: WITHDRAWAL_STATES, WithdrawalError, approveWithdrawal, broadcastKeyFor, canTransition, confirmWithdrawal, describeSweep, holdReference, markFailed, processOnce, refundFailed, rejectWithdrawal, requestWithdrawal, sweepForPayout. Named type imports: Broadcaster, SweepCandidate, SweepPlan, Withdrawal, WithdrawalState. Import only the names used by this file.
|
|
593
|
+
|
|
594
|
+
```text
|
|
595
|
+
import { WITHDRAWAL_STATES, WithdrawalError, approveWithdrawal, broadcastKeyFor, canTransition, confirmWithdrawal } from '@forgezero/runtime/finance/chain-withdrawals';
|
|
596
|
+
import { describeSweep, holdReference, markFailed, processOnce, refundFailed, rejectWithdrawal } from '@forgezero/runtime/finance/chain-withdrawals';
|
|
597
|
+
import { requestWithdrawal, sweepForPayout } from '@forgezero/runtime/finance/chain-withdrawals';
|
|
598
|
+
import type { Broadcaster, SweepCandidate, SweepPlan, Withdrawal, WithdrawalState } from '@forgezero/runtime/finance/chain-withdrawals';
|
|
599
|
+
```
|
|
600
|
+
|
|
601
|
+
<a id="forgezero-runtime-finance-chain-reconcile"></a>
|
|
602
|
+
## @forgezero/runtime/finance/chain-reconcile
|
|
603
|
+
|
|
604
|
+
Deterministic reconciliation between chain observations and durable transfer state. Named value imports: DISCREPANCY_KINDS, ReconcileError, reconcileOnce, reconcileReport, shortfallUsd. Named type imports: Discrepancy, DiscrepancyKind, LedgerLiability, OnChainHolding, ReconcileReport. Import only the names used by this file.
|
|
605
|
+
|
|
606
|
+
```text
|
|
607
|
+
import { DISCREPANCY_KINDS, ReconcileError, reconcileOnce, reconcileReport, shortfallUsd } from '@forgezero/runtime/finance/chain-reconcile';
|
|
608
|
+
import type { Discrepancy, DiscrepancyKind, LedgerLiability, OnChainHolding, ReconcileReport } from '@forgezero/runtime/finance/chain-reconcile';
|
|
609
|
+
```
|
|
610
|
+
|
|
611
|
+
<a id="forgezero-runtime-finance-market"></a>
|
|
612
|
+
## @forgezero/runtime/finance/market
|
|
613
|
+
|
|
614
|
+
Market order, fill and quote contracts independent of any exchange adapter. Named value imports: MarketError, createFeed, disagreementOf, isStale, lastPrice, limitFor, stalenessOf, subscribe. Named type imports: Feed, FeedEvent, FeedOptions, PriceResult, Quote, StalenessPolicy, VenueSource. Import only the names used by this file.
|
|
615
|
+
|
|
616
|
+
```text
|
|
617
|
+
import { MarketError, createFeed, disagreementOf, isStale, lastPrice, limitFor } from '@forgezero/runtime/finance/market';
|
|
618
|
+
import { stalenessOf, subscribe } from '@forgezero/runtime/finance/market';
|
|
619
|
+
import type { Feed, FeedEvent, FeedOptions, PriceResult, Quote, StalenessPolicy } from '@forgezero/runtime/finance/market';
|
|
620
|
+
import type { VenueSource } from '@forgezero/runtime/finance/market';
|
|
621
|
+
```
|
|
622
|
+
|
|
623
|
+
<a id="forgezero-runtime-custody-share"></a>
|
|
624
|
+
## @forgezero/runtime/custody-share
|
|
625
|
+
|
|
626
|
+
Threshold-share parsing, validation and reconstruction. Named value imports: PROBE_BYTES, factorWrapAad, joinProbeAndShare, openFactorEnvelope, openSealedToFactor, openShareWithPasskey, openShareWithPhrase, passkeyWrappingKey, phraseWrappingKey, sealShare, shareIndexOf, splitProbeAndShare, wrappingKeysFor. Named type imports: SealedShare, WrappingKeys. Import only the names used by this file.
|
|
627
|
+
|
|
628
|
+
```text
|
|
629
|
+
import { PROBE_BYTES, factorWrapAad, joinProbeAndShare, openFactorEnvelope, openSealedToFactor, openShareWithPasskey } from '@forgezero/runtime/custody-share';
|
|
630
|
+
import { openShareWithPhrase, passkeyWrappingKey, phraseWrappingKey, sealShare, shareIndexOf, splitProbeAndShare } from '@forgezero/runtime/custody-share';
|
|
631
|
+
import { wrappingKeysFor } from '@forgezero/runtime/custody-share';
|
|
632
|
+
import type { SealedShare, WrappingKeys } from '@forgezero/runtime/custody-share';
|
|
633
|
+
```
|
|
634
|
+
|
|
635
|
+
<a id="forgezero-runtime-custody-crypto"></a>
|
|
636
|
+
## @forgezero/runtime/custody-crypto
|
|
637
|
+
|
|
638
|
+
Hybrid ML-KEM-768 plus X25519 custody-share sealing and opening. Named value imports: deriveKey, openFromKey, openWithKey, sealToKey, sealWithKey, wrappingKeyPair. Named type imports: CipherBox, SealedToKey. Import only the names used by this file.
|
|
639
|
+
|
|
640
|
+
```text
|
|
641
|
+
import { deriveKey, openFromKey, openWithKey, sealToKey, sealWithKey, wrappingKeyPair } from '@forgezero/runtime/custody-crypto';
|
|
642
|
+
import type { CipherBox, SealedToKey } from '@forgezero/runtime/custody-crypto';
|
|
643
|
+
```
|
|
644
|
+
|
|
645
|
+
## 1. Install, then import a subpath
|
|
646
|
+
|
|
647
|
+
There is no root export, and that is deliberate. `import from "@forgezero/runtime"` is meant to fail rather than resolve to whichever module happened to be listed first — a bare import that silently works is how a project ends up depending on the whole package to use one function. Every module is its own entry point, so a bundler includes what you imported and nothing else.
|
|
648
|
+
|
|
649
|
+
```text
|
|
650
|
+
bun add @forgezero/runtime
|
|
651
|
+
|
|
16
652
|
import { parseAmount } from '@forgezero/runtime/finance/money';
|
|
17
653
|
import { createScheduler } from '@forgezero/runtime/jobs';
|
|
18
654
|
|
|
19
|
-
//
|
|
20
|
-
//
|
|
655
|
+
// This throws. It is supposed to.
|
|
656
|
+
// import { anything } from '@forgezero/runtime';
|
|
21
657
|
```
|
|
22
658
|
|
|
23
659
|
## What is in it
|
|
24
660
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
661
|
+
Four groups. The service spine is what a process needs to keep working after the response is sent; the record keeps evidence; the finance modules are the ones that must never be approximated. Nothing here knows what your product does — a tenant binds its own business rules to these, it does not fork them.
|
|
662
|
+
|
|
663
|
+
```text
|
|
664
|
+
SPINE jobs scheduled work submitted through the common queue
|
|
665
|
+
queue awaited result; parallel keys, sequential within one
|
|
666
|
+
outbox business-owned durability, drained through handlers
|
|
667
|
+
|
|
668
|
+
RECORD audit append-only, hash-chained, names the first altered row
|
|
669
|
+
backup encrypted, chunked, verified snapshots + the restore
|
|
670
|
+
compliance screening as a decision record, failing closed
|
|
671
|
+
calendar billing periods, working days, holidays, due dates
|
|
672
|
+
|
|
673
|
+
IDENTITY identity hybrid Ed25519 + ML-DSA-65 request signing
|
|
674
|
+
totp RFC 6238, asymmetric window, replay rejected
|
|
675
|
+
notify named templates to text and HTML, escaped per part
|
|
676
|
+
schema JSON Schema validation, restricted and describable
|
|
677
|
+
|
|
678
|
+
FINANCE money minor units with the asset attached
|
|
679
|
+
storage the same amount, exact AND sortable in a database
|
|
680
|
+
ledger double-entry postings and derived balances
|
|
681
|
+
commission profit net of flows, high-water mark, referral split
|
|
682
|
+
rates what an asset is worth, and how old that answer is
|
|
683
|
+
transfers deposits and withdrawals as ordered pipelines
|
|
684
|
+
tax who may tax a sale, and who accounts for it
|
|
685
|
+
chain chains, assets, confirmation depth by value band
|
|
686
|
+
custody CREATE2 deposit addresses and EIP-712 digests
|
|
687
|
+
derive declare a key ForgeZero generates, not the tenant
|
|
688
|
+
venues trading venues, market types and symbols as data
|
|
689
|
+
binance Binance behind the venue adapter
|
|
690
|
+
```
|
|
691
|
+
|
|
692
|
+
## Optional peers — install only what your subpath needs
|
|
31
693
|
|
|
32
|
-
|
|
33
|
-
do not fork them.
|
|
694
|
+
Nothing third-party is bundled. Vendoring a crypto library means a fix for it never reaches you until this package is republished, so the imports stay real and the dependency stays yours. Most subpaths need nothing; four of them do, and the failure is a plain module-not-found rather than a silently wrong result.
|
|
34
695
|
|
|
35
|
-
|
|
696
|
+
```text
|
|
697
|
+
# most subpaths: nothing to add
|
|
36
698
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
wire values; outputs are checked strictly so a wrong handler result cannot be
|
|
40
|
-
coerced into looking correct.
|
|
699
|
+
# finance/custody — CREATE2 and EIP-712 digests
|
|
700
|
+
bun add @noble/hashes
|
|
41
701
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
import { typeboxQueryCodec, T } from '@forgezero/runtime/schema/typebox';
|
|
702
|
+
# identity — hybrid post-quantum signing
|
|
703
|
+
bun add @noble/curves @noble/post-quantum
|
|
45
704
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
output: typeboxQueryCodec(T.Object({ total: T.String() }))
|
|
50
|
-
});
|
|
705
|
+
# schema/typebox — only if you validate with TypeBox
|
|
706
|
+
bun add @sinclair/typebox
|
|
707
|
+
```
|
|
51
708
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
709
|
+
## Money is never a number
|
|
710
|
+
|
|
711
|
+
An amount is minor units as a bigint with its asset attached, so two currencies cannot be added by accident and a rounding mode is always stated. A database needs a second thing the bigint cannot give it — an ORDER BY that works — so `finance/storage` writes both: the authoritative string, and a lossy double used for sorting and range filters only. One ETH is 10^18 minor units and a signed 64-bit column overflows at about nine ETH, which is why the exact value is never the sortable one.
|
|
712
|
+
|
|
713
|
+
```text
|
|
714
|
+
import { parseAmount, mulRate, formatAmount } from '@forgezero/runtime/finance/money';
|
|
715
|
+
import { toStored, rangeBounds } from '@forgezero/runtime/finance/storage';
|
|
716
|
+
|
|
717
|
+
const fee = mulRate(parseAmount('1250.00', 'USD'), '0.015', 'down');
|
|
718
|
+
formatAmount(fee); // '18.75' — never 18.749999999
|
|
719
|
+
|
|
720
|
+
const row = toStored(fee);
|
|
721
|
+
// { units: '1875', value: '18.75', asset: 'USD', sort: 18.75 }
|
|
722
|
+
// units → what you pay out. sort → what you ORDER BY.
|
|
723
|
+
|
|
724
|
+
rangeBounds(parseAmount('10', 'USD'), null); // { gte: 10 }
|
|
55
725
|
```
|
|
56
726
|
|
|
57
|
-
##
|
|
727
|
+
## The contracts ship with it
|
|
728
|
+
|
|
729
|
+
The Solidity behind `finance/custody` is in the package rather than in a repository you have to go find. `finance/custody` computes the counterfactual address; `DepositFactory` is what makes that address real on first sweep, and `ColdVault` is the M-of-N EIP-712 approval the digests are built for. Address arithmetic without the contract that honours it is half an answer.
|
|
58
730
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
731
|
+
```text
|
|
732
|
+
node_modules/@forgezero/runtime/contracts/src/
|
|
733
|
+
DepositProxy.sol lazily deployed at first sweep — no key, no gas per address
|
|
734
|
+
DepositFactory.sol CREATE2, salt opaque to the contract
|
|
735
|
+
ColdVault.sol M-of-N, signatures ordered by ascending signer
|
|
736
|
+
SafeTransferLib.sol tokens that do not return a bool
|
|
737
|
+
```
|
|
64
738
|
|
|
65
|
-
|
|
66
|
-
import { createQueue } from '@forgezero/runtime/queue';
|
|
739
|
+
## Jobs — background work that never overlaps
|
|
67
740
|
|
|
68
|
-
|
|
69
|
-
// Use `width` for an exact ceiling, or an explicit dynamic resource policy:
|
|
70
|
-
const queue = createQueue({ resources: { percent: 60, reserve: 1, max: 32 } });
|
|
71
|
-
const task = queue.run('tenant-a:wallet-7', transfer, amount, destination);
|
|
72
|
-
const receipt = await task.result;
|
|
741
|
+
The lock and the cursor store are interfaces, so this runs against a database, Redis, or nothing at all in a test.
|
|
73
742
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
queue.stopKey('tenant-a:wallet-7'); // running finishes; pending is rejected
|
|
77
|
-
queue.startKey('tenant-a:wallet-7');
|
|
78
|
-
queue.cancel(task.id); // pending task only
|
|
79
|
-
await queue.stop(30_000); // close intake and drain all work
|
|
743
|
+
```text
|
|
744
|
+
import { createScheduler, defineJob, cursorJob } from '@forgezero/runtime/jobs';
|
|
80
745
|
```
|
|
81
746
|
|
|
82
|
-
|
|
83
|
-
multi-core merely by entering a queue: put that handler in Bun/standard Workers
|
|
84
|
-
and await the Worker result from the queue.
|
|
747
|
+
## Never setInterval
|
|
85
748
|
|
|
86
|
-
|
|
87
|
-
IANA timezone and weekday filter. `overlap: 'wait'` (the default) schedules the
|
|
88
|
-
next run after completion; `overlap: 'skip'` keeps clock cadence and drops a tick
|
|
89
|
-
when the same key is still busy. Same-key overlap is never allowed.
|
|
749
|
+
An interval fires whether or not the previous run finished, so work that takes longer than its period ends up running twice over the same data. The next run is scheduled after the current one completes, which makes the overlap impossible rather than unlikely.
|
|
90
750
|
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
751
|
+
```text
|
|
752
|
+
const scheduler = createScheduler({
|
|
753
|
+
jobs: [
|
|
754
|
+
defineJob({ key: 'reap-sessions', label: 'Reap sessions', every: '5m', run: reap }),
|
|
755
|
+
defineJob({ key: 'probe-providers', label: 'Probe providers', every: '30s', run: probe })
|
|
756
|
+
],
|
|
757
|
+
lock: storeLock(lockStore)
|
|
98
758
|
});
|
|
759
|
+
|
|
760
|
+
scheduler.start();
|
|
99
761
|
```
|
|
100
762
|
|
|
101
|
-
##
|
|
763
|
+
## A lease, not a mutex
|
|
102
764
|
|
|
103
|
-
|
|
104
|
-
asset attached, so two currencies cannot be added by accident and a rounding
|
|
105
|
-
mode is always stated. `finance/storage` writes the same amount twice — the
|
|
106
|
-
authoritative string, and a lossy double used for `ORDER BY` only. One ETH is
|
|
107
|
-
10^18 minor units and a signed 64-bit column overflows around nine ETH, which is
|
|
108
|
-
why the exact value is never the sortable one.
|
|
765
|
+
A process that dies holding a mutex blocks its job for ever, and somebody clears it by hand at three in the morning. A lease expires on its own. The fence number rises each time the lock is granted, so a run that stalled past its lease and woke up finds its fence stale and stops before writing.
|
|
109
766
|
|
|
110
|
-
```
|
|
111
|
-
const
|
|
112
|
-
|
|
113
|
-
toStored(fee); // { units: '1875', value: '18.75', asset: 'USD', sort: 18.75 }
|
|
767
|
+
```text
|
|
768
|
+
const lease = await lock.acquire('scan', 60_000); // undefined if held
|
|
769
|
+
await lock.renew('scan', lease.fence, 60_000); // false once superseded
|
|
114
770
|
```
|
|
115
771
|
|
|
116
|
-
|
|
117
|
-
run finished, so work slower than its period runs twice over the same data. The
|
|
118
|
-
next run is scheduled after the current one completes. The lock is a lease with
|
|
119
|
-
a fence, not a mutex — a process that dies does not block its job for ever.
|
|
772
|
+
## The cursor advances only on a complete batch
|
|
120
773
|
|
|
121
|
-
|
|
122
|
-
then write the cursor — never per item, never before. Item three of ten throwing
|
|
123
|
-
retries the whole batch from the same position, which means `process` must be
|
|
124
|
-
idempotent, and idempotent retries beat records nobody ever looks at again.
|
|
774
|
+
Fetch a batch, process every item, then write the cursor — never per item and never before. If item three of ten throws, the whole batch is retried from the same position. That means process must be idempotent, and idempotent retries are strictly better than the alternative, which is records nobody ever looks at again.
|
|
125
775
|
|
|
126
|
-
|
|
776
|
+
```text
|
|
777
|
+
cursorJob({
|
|
778
|
+
key: 'scan-deposits',
|
|
779
|
+
label: 'Scan deposits',
|
|
780
|
+
every: '15s',
|
|
781
|
+
store: cursors,
|
|
782
|
+
from: '0',
|
|
783
|
+
fetch: (cursor) => fetchBlocks(cursor),
|
|
784
|
+
process: (transfer) => credit(transfer) // keyed, so a retry is free
|
|
785
|
+
});
|
|
786
|
+
```
|
|
127
787
|
|
|
128
|
-
|
|
129
|
-
never reaches you until this package republishes. Most subpaths need nothing:
|
|
788
|
+
## Stop waits
|
|
130
789
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
790
|
+
Returning from stop() before in-flight work settles is how a deploy leaves a record half-written and the next boot finds state nothing explains. Timers are cleared, the abort signal fires so long runs can cut themselves short, and then it awaits what is still running.
|
|
791
|
+
|
|
792
|
+
```text
|
|
793
|
+
await scheduler.stop(); // clears timers, aborts, awaits in-flight
|
|
794
|
+
scheduler.pause(); // stop scheduling, let in-flight finish
|
|
795
|
+
await scheduler.runNow('scan-deposits');
|
|
135
796
|
```
|
|
136
797
|
|
|
137
|
-
##
|
|
798
|
+
## Status somebody can read during an incident
|
|
138
799
|
|
|
139
|
-
|
|
140
|
-
contracts that make those addresses real are in the tarball, not in a repository
|
|
141
|
-
you have to go find.
|
|
800
|
+
Last run, duration, result, error and consecutive failures per job. Without it a job that has been failing for a week looks exactly like a job that has been succeeding.
|
|
142
801
|
|
|
802
|
+
```text
|
|
803
|
+
scheduler.status();
|
|
804
|
+
// [{ key: 'scan-deposits', state: 'idle', runs: 412,
|
|
805
|
+
// lastDurationMs: 840, lastResult: { processed: 17, batches: 2 },
|
|
806
|
+
// consecutiveFailures: 0, skippedLocked: 0 }]
|
|
143
807
|
```
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
808
|
+
|
|
809
|
+
## Schema — validation you can also render
|
|
810
|
+
|
|
811
|
+
TypeBox is a peer dependency and optional. A project on Zod pulls none of it, because the interface is what the other packages depend on.
|
|
812
|
+
|
|
813
|
+
```text
|
|
814
|
+
import { validate, describeForm } from '@forgezero/runtime/schema';
|
|
815
|
+
|
|
816
|
+
// only if you validate with TypeBox
|
|
817
|
+
bun add @sinclair/typebox
|
|
148
818
|
```
|
|
149
819
|
|
|
150
|
-
|
|
820
|
+
## 2. Validate
|
|
821
|
+
|
|
822
|
+
Query strings are entirely strings, so values are converted before checking — otherwise ?port=587 fails a schema expecting a number on a perfectly well-formed request.
|
|
823
|
+
|
|
824
|
+
```text
|
|
825
|
+
import { typebox, T } from '@forgezero/runtime/schema/typebox';
|
|
826
|
+
|
|
827
|
+
const Config = T.Object(
|
|
828
|
+
{ host: T.String(), port: T.Integer() },
|
|
829
|
+
{ additionalProperties: false }
|
|
830
|
+
);
|
|
831
|
+
|
|
832
|
+
typebox.validate(Config, { host: 'mail', port: '587' });
|
|
833
|
+
// { ok: true, value: { host: 'mail', port: 587 } }
|
|
834
|
+
```
|
|
835
|
+
|
|
836
|
+
## 3. Render a form from it
|
|
837
|
+
|
|
838
|
+
describeForm turns a schema into flat, framework-agnostic fields. This is what lets an admin screen render provider credentials and security factors with no per-feature UI code.
|
|
151
839
|
|
|
152
|
-
|
|
840
|
+
```text
|
|
841
|
+
typebox.describeForm(Config);
|
|
842
|
+
// [{ path: 'host', label: 'Host', kind: 'string', required: true }, ...]
|
|
843
|
+
```
|
|
844
|
+
|
|
845
|
+
## The restrictions are a security boundary
|
|
846
|
+
|
|
847
|
+
A schema authored in your own source is trusted. One submitted by a tenant is not, and these limits are the only thing between the two. $ref would let a schema point validation at a document you do not control; unbounded depth is a denial-of-service; and an object accepting unknown properties is one that lets an unvalidated field ride into an envelope.
|
|
848
|
+
|
|
849
|
+
```text
|
|
850
|
+
typebox.restrict(schema)
|
|
851
|
+
|
|
852
|
+
$ref · $id · $defs refused
|
|
853
|
+
depth > 4 refused
|
|
854
|
+
more than 100 fields refused
|
|
855
|
+
larger than 64 KiB refused
|
|
856
|
+
additionalProperties must be false
|
|
857
|
+
```
|
|
858
|
+
|
|
859
|
+
## writeOnly is the vault boundary
|
|
860
|
+
|
|
861
|
+
A field marked writeOnly is never returned to a browser. readableFields strips them at any depth, and writeOnlyPaths lists exactly what must be routed to secret storage instead.
|
|
862
|
+
|
|
863
|
+
```text
|
|
864
|
+
const fields = typebox.describeForm(schema);
|
|
865
|
+
|
|
866
|
+
readableFields(fields); // safe to serialise
|
|
867
|
+
writeOnlyPaths(fields); // ['apiKey', 'nested.secret']
|
|
868
|
+
```
|
|
869
|
+
|
|
870
|
+
## Adding another validator
|
|
871
|
+
|
|
872
|
+
Implement four functions. toJsonSchema is what keeps the ecosystem from fragmenting: stored config, the admin UI and the wire all speak JSON Schema, so a Zod project and a TypeBox project produce identical documents and either can read the other.
|
|
873
|
+
|
|
874
|
+
```text
|
|
875
|
+
interface SchemaValidator<S> {
|
|
876
|
+
name: string;
|
|
877
|
+
validate(schema: S, value: unknown): ValidationResult;
|
|
878
|
+
describeForm(schema: S): FormField[];
|
|
879
|
+
toJsonSchema(schema: S): Record<string, unknown>;
|
|
880
|
+
restrict(schema: S, limits?: Restrictions): S;
|
|
881
|
+
}
|
|
882
|
+
```
|
|
153
883
|
|
|
154
|
-
|
|
155
|
-
deploys — and usable entirely on its own, with no ForgeZero account.
|
|
884
|
+
Full rendered documentation: https://www.forgezero.net/docs/runtime
|