@secondlayer/shared 7.11.2 → 9.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/archive/range-digest.d.ts +16 -169
- package/dist/src/archive/semantic-digest-builder.d.ts +16 -169
- package/dist/src/archive/status.js +11 -3
- package/dist/src/archive/status.js.map +3 -3
- package/dist/src/coverage/index.d.ts +15 -169
- package/dist/src/crypto/secrets.js +22 -3
- package/dist/src/crypto/secrets.js.map +3 -3
- package/dist/src/db/index.d.ts +18 -211
- package/dist/src/db/index.js +23 -16
- package/dist/src/db/index.js.map +4 -4
- package/dist/src/db/queries/chain-reorgs.d.ts +16 -169
- package/dist/src/db/queries/chain-reorgs.js +23 -16
- package/dist/src/db/queries/chain-reorgs.js.map +4 -4
- package/dist/src/db/queries/contracts.d.ts +16 -169
- package/dist/src/db/queries/instance.d.ts +16 -169
- package/dist/src/db/queries/integrity.d.ts +16 -169
- package/dist/src/db/queries/subgraph-gaps.d.ts +16 -169
- package/dist/src/db/queries/subgraph-operations.d.ts +17 -170
- package/dist/src/db/queries/subgraph-operations.js +1 -15
- package/dist/src/db/queries/subgraph-operations.js.map +3 -3
- package/dist/src/db/queries/subgraphs.d.ts +17 -191
- package/dist/src/db/queries/subgraphs.js +30 -1068
- package/dist/src/db/queries/subgraphs.js.map +5 -12
- package/dist/src/db/queries/subscriptions.d.ts +16 -169
- package/dist/src/db/queries/subscriptions.js +22 -3
- package/dist/src/db/queries/subscriptions.js.map +3 -3
- package/dist/src/db/queries/sync-scope.d.ts +1006 -0
- package/dist/src/db/queries/sync-scope.js +116 -0
- package/dist/src/db/queries/sync-scope.js.map +10 -0
- package/dist/src/db/schema.d.ts +17 -198
- package/dist/src/errors.d.ts +1 -22
- package/dist/src/errors.js +2 -4
- package/dist/src/errors.js.map +3 -3
- package/dist/src/index.d.ts +22 -256
- package/dist/src/index.js +24 -20
- package/dist/src/index.js.map +6 -6
- package/dist/src/mode.d.ts +16 -2
- package/dist/src/mode.js +25 -4
- package/dist/src/mode.js.map +3 -3
- package/dist/src/node/local-client.d.ts +16 -169
- package/dist/src/runtime/index.d.ts +137 -18
- package/dist/src/runtime/index.js +261 -41
- package/dist/src/runtime/index.js.map +9 -7
- package/dist/src/schemas/index.d.ts +5 -25
- package/dist/src/schemas/index.js +1 -2
- package/dist/src/schemas/index.js.map +3 -3
- package/dist/src/schemas/subgraphs.d.ts +5 -25
- package/dist/src/schemas/subgraphs.js +1 -2
- package/dist/src/schemas/subgraphs.js.map +3 -3
- package/dist/src/streams-rows/index.d.ts +399 -0
- package/dist/src/streams-rows/index.js +336 -0
- package/dist/src/streams-rows/index.js.map +17 -0
- package/dist/src/subgraphs/spec.d.ts +0 -9
- package/migrations/0118_drop_retired_control_tables.ts +53 -0
- package/migrations/0119_drop_accounts_plan.ts +29 -0
- package/migrations/0120_sync_scopes.ts +42 -0
- package/package.json +10 -6
- package/dist/src/x402.d.ts +0 -47
- package/dist/src/x402.js +0 -79
- package/dist/src/x402.js.map +0 -10
package/dist/src/mode.d.ts
CHANGED
|
@@ -10,14 +10,28 @@
|
|
|
10
10
|
* 2026-05-14 shared-rip this also serves subgraphs + subscriptions.
|
|
11
11
|
*/
|
|
12
12
|
type InstanceMode = "oss" | "platform";
|
|
13
|
+
/** What the operator wrote in the env — `archive` is the honest name for the
|
|
14
|
+
* metered public-archive deployment and aliases `platform` behaviorally. */
|
|
15
|
+
type DeclaredInstanceMode = InstanceMode | "archive";
|
|
13
16
|
/**
|
|
14
17
|
* Resolve the active instance mode from `process.env.INSTANCE_MODE`.
|
|
15
18
|
* Defaults to `"oss"` — the safest default for self-hosters who deploy
|
|
16
|
-
* without setting the variable.
|
|
19
|
+
* without setting the variable. `archive` normalizes to `platform` here so
|
|
20
|
+
* every behavioral branch stays a two-way choice; use
|
|
21
|
+
* `getDeclaredInstanceMode()` for display surfaces.
|
|
17
22
|
*/
|
|
18
23
|
declare function getInstanceMode(): InstanceMode;
|
|
24
|
+
/** The mode as declared in the env, for status/identity surfaces. */
|
|
25
|
+
declare function getDeclaredInstanceMode(): DeclaredInstanceMode;
|
|
26
|
+
/**
|
|
27
|
+
* True when public reads are credit-metered (the free window, retention, and
|
|
28
|
+
* credits gates arm). Platform/archive deployments meter by default;
|
|
29
|
+
* self-host never does unless the operator explicitly sets
|
|
30
|
+
* `METERED_READS=true`. `METERED_READS=false` disarms a metered deployment.
|
|
31
|
+
*/
|
|
32
|
+
declare function isMeteredReads(): boolean;
|
|
19
33
|
/** True when the active mode is `"platform"` (shared multi-tenant). */
|
|
20
34
|
declare function isPlatformMode(): boolean;
|
|
21
35
|
/** True when the active mode is `"oss"` (self-hosted). */
|
|
22
36
|
declare function isOssMode(): boolean;
|
|
23
|
-
export { isPlatformMode, isOssMode, getInstanceMode, InstanceMode };
|
|
37
|
+
export { isPlatformMode, isOssMode, isMeteredReads, getInstanceMode, getDeclaredInstanceMode, InstanceMode, DeclaredInstanceMode };
|
package/dist/src/mode.js
CHANGED
|
@@ -15,14 +15,33 @@ var __export = (target, all) => {
|
|
|
15
15
|
};
|
|
16
16
|
|
|
17
17
|
// src/mode.ts
|
|
18
|
-
var VALID_MODES = [
|
|
19
|
-
|
|
18
|
+
var VALID_MODES = [
|
|
19
|
+
"oss",
|
|
20
|
+
"platform",
|
|
21
|
+
"archive"
|
|
22
|
+
];
|
|
23
|
+
function declaredMode() {
|
|
20
24
|
const raw = process.env.INSTANCE_MODE?.trim().toLowerCase();
|
|
21
25
|
if (raw && VALID_MODES.includes(raw)) {
|
|
22
26
|
return raw;
|
|
23
27
|
}
|
|
24
28
|
return "oss";
|
|
25
29
|
}
|
|
30
|
+
function getInstanceMode() {
|
|
31
|
+
const declared = declaredMode();
|
|
32
|
+
return declared === "archive" ? "platform" : declared;
|
|
33
|
+
}
|
|
34
|
+
function getDeclaredInstanceMode() {
|
|
35
|
+
return declaredMode();
|
|
36
|
+
}
|
|
37
|
+
function isMeteredReads() {
|
|
38
|
+
const override = process.env.METERED_READS?.trim().toLowerCase();
|
|
39
|
+
if (override === "true")
|
|
40
|
+
return true;
|
|
41
|
+
if (override === "false")
|
|
42
|
+
return false;
|
|
43
|
+
return getInstanceMode() === "platform";
|
|
44
|
+
}
|
|
26
45
|
function isPlatformMode() {
|
|
27
46
|
return getInstanceMode() === "platform";
|
|
28
47
|
}
|
|
@@ -32,8 +51,10 @@ function isOssMode() {
|
|
|
32
51
|
export {
|
|
33
52
|
isPlatformMode,
|
|
34
53
|
isOssMode,
|
|
35
|
-
|
|
54
|
+
isMeteredReads,
|
|
55
|
+
getInstanceMode,
|
|
56
|
+
getDeclaredInstanceMode
|
|
36
57
|
};
|
|
37
58
|
|
|
38
|
-
//# debugId=
|
|
59
|
+
//# debugId=F90A93497EE7AEC664756E2164756E21
|
|
39
60
|
//# sourceMappingURL=mode.js.map
|
package/dist/src/mode.js.map
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/mode.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"/**\n * Instance modes for the Secondlayer platform.\n *\n * - `oss`: self-hosted, single-tenant. No auth middleware, no platform routes\n * (projects, admin). Everything runs against a single `DATABASE_URL`.\n * Intended for `docker compose up`.\n *\n * - `platform`: control-plane mode. Magic-link auth, API keys, projects,\n * admin. Serves the dashboard + CLI against a single shared DB. Post\n * 2026-05-14 shared-rip this also serves subgraphs + subscriptions.\n */\n\nexport type InstanceMode = \"oss\" | \"platform\";\n\nconst VALID_MODES: readonly
|
|
5
|
+
"/**\n * Instance modes for the Secondlayer platform.\n *\n * - `oss`: self-hosted, single-tenant. No auth middleware, no platform routes\n * (projects, admin). Everything runs against a single `DATABASE_URL`.\n * Intended for `docker compose up`.\n *\n * - `platform`: control-plane mode. Magic-link auth, API keys, projects,\n * admin. Serves the dashboard + CLI against a single shared DB. Post\n * 2026-05-14 shared-rip this also serves subgraphs + subscriptions.\n */\n\nexport type InstanceMode = \"oss\" | \"platform\";\n\n/** What the operator wrote in the env — `archive` is the honest name for the\n * metered public-archive deployment and aliases `platform` behaviorally. */\nexport type DeclaredInstanceMode = InstanceMode | \"archive\";\n\nconst VALID_MODES: readonly DeclaredInstanceMode[] = [\n\t\"oss\",\n\t\"platform\",\n\t\"archive\",\n];\n\nfunction declaredMode(): DeclaredInstanceMode {\n\tconst raw = process.env.INSTANCE_MODE?.trim().toLowerCase();\n\tif (raw && (VALID_MODES as readonly string[]).includes(raw)) {\n\t\treturn raw as DeclaredInstanceMode;\n\t}\n\treturn \"oss\";\n}\n\n/**\n * Resolve the active instance mode from `process.env.INSTANCE_MODE`.\n * Defaults to `\"oss\"` — the safest default for self-hosters who deploy\n * without setting the variable. `archive` normalizes to `platform` here so\n * every behavioral branch stays a two-way choice; use\n * `getDeclaredInstanceMode()` for display surfaces.\n */\nexport function getInstanceMode(): InstanceMode {\n\tconst declared = declaredMode();\n\treturn declared === \"archive\" ? \"platform\" : declared;\n}\n\n/** The mode as declared in the env, for status/identity surfaces. */\nexport function getDeclaredInstanceMode(): DeclaredInstanceMode {\n\treturn declaredMode();\n}\n\n/**\n * True when public reads are credit-metered (the free window, retention, and\n * credits gates arm). Platform/archive deployments meter by default;\n * self-host never does unless the operator explicitly sets\n * `METERED_READS=true`. `METERED_READS=false` disarms a metered deployment.\n */\nexport function isMeteredReads(): boolean {\n\tconst override = process.env.METERED_READS?.trim().toLowerCase();\n\tif (override === \"true\") return true;\n\tif (override === \"false\") return false;\n\treturn getInstanceMode() === \"platform\";\n}\n\n/** True when the active mode is `\"platform\"` (shared multi-tenant). */\nexport function isPlatformMode(): boolean {\n\treturn getInstanceMode() === \"platform\";\n}\n\n/** True when the active mode is `\"oss\"` (self-hosted). */\nexport function isOssMode(): boolean {\n\treturn getInstanceMode() === \"oss\";\n}\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": ";;;;;;;;;;;;;;;;;
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": ";;;;;;;;;;;;;;;;;AAkBA,IAAM,cAA+C;AAAA,EACpD;AAAA,EACA;AAAA,EACA;AACD;AAEA,SAAS,YAAY,GAAyB;AAAA,EAC7C,MAAM,MAAM,QAAQ,IAAI,eAAe,KAAK,EAAE,YAAY;AAAA,EAC1D,IAAI,OAAQ,YAAkC,SAAS,GAAG,GAAG;AAAA,IAC5D,OAAO;AAAA,EACR;AAAA,EACA,OAAO;AAAA;AAUD,SAAS,eAAe,GAAiB;AAAA,EAC/C,MAAM,WAAW,aAAa;AAAA,EAC9B,OAAO,aAAa,YAAY,aAAa;AAAA;AAIvC,SAAS,uBAAuB,GAAyB;AAAA,EAC/D,OAAO,aAAa;AAAA;AASd,SAAS,cAAc,GAAY;AAAA,EACzC,MAAM,WAAW,QAAQ,IAAI,eAAe,KAAK,EAAE,YAAY;AAAA,EAC/D,IAAI,aAAa;AAAA,IAAQ,OAAO;AAAA,EAChC,IAAI,aAAa;AAAA,IAAS,OAAO;AAAA,EACjC,OAAO,gBAAgB,MAAM;AAAA;AAIvB,SAAS,cAAc,GAAY;AAAA,EACzC,OAAO,gBAAgB,MAAM;AAAA;AAIvB,SAAS,SAAS,GAAY;AAAA,EACpC,OAAO,gBAAgB,MAAM;AAAA;",
|
|
8
|
+
"debugId": "F90A93497EE7AEC664756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
|
@@ -18,6 +18,7 @@ declare const FAILURE_CLASSES: readonly ["omission", "version", "digest_mismatch
|
|
|
18
18
|
type FailureClass = (typeof FAILURE_CLASSES)[number];
|
|
19
19
|
declare const RETRY_STATES: readonly ["open", "retrying", "halted", "resolved"];
|
|
20
20
|
type RetryState = (typeof RETRY_STATES)[number];
|
|
21
|
+
type BootstrapSource = "archive" | "genesis" | "import";
|
|
21
22
|
interface BlocksTable {
|
|
22
23
|
height: number;
|
|
23
24
|
hash: string;
|
|
@@ -223,11 +224,9 @@ interface AccountsTable {
|
|
|
223
224
|
ghost: Generated<boolean>;
|
|
224
225
|
/** Stacks principal owning a wallet-ghost account (x402-paid deploys). */
|
|
225
226
|
wallet_principal: string | null;
|
|
226
|
-
plan: Generated<string>;
|
|
227
227
|
display_name: string | null;
|
|
228
228
|
bio: string | null;
|
|
229
229
|
avatar_url: string | null;
|
|
230
|
-
slug: string | null;
|
|
231
230
|
stripe_customer_id: string | null;
|
|
232
231
|
/** Opt-out toggle for the subgraph reindex-completion email. Defaults true. */
|
|
233
232
|
notify_reindex_complete: Generated<boolean>;
|
|
@@ -244,19 +243,6 @@ interface SessionsTable {
|
|
|
244
243
|
last_used_at: Date | null;
|
|
245
244
|
created_at: Generated<Date>;
|
|
246
245
|
}
|
|
247
|
-
/**
|
|
248
|
-
* One-time claim tokens for ghost accounts. The raw token only ever appears in
|
|
249
|
-
* the claim URL returned at mint time; we store its sha256. A used token marks
|
|
250
|
-
* the account as claimed (or merged into an existing account).
|
|
251
|
-
*/
|
|
252
|
-
interface ClaimTokensTable {
|
|
253
|
-
id: Generated<string>;
|
|
254
|
-
account_id: string;
|
|
255
|
-
token_hash: string;
|
|
256
|
-
created_at: Generated<Date>;
|
|
257
|
-
expires_at: Date;
|
|
258
|
-
used_at: Date | null;
|
|
259
|
-
}
|
|
260
246
|
interface MagicLinksTable {
|
|
261
247
|
id: Generated<string>;
|
|
262
248
|
email: string;
|
|
@@ -267,47 +253,6 @@ interface MagicLinksTable {
|
|
|
267
253
|
failed_attempts: Generated<number>;
|
|
268
254
|
created_at: Generated<Date>;
|
|
269
255
|
}
|
|
270
|
-
interface UsageDailyTable {
|
|
271
|
-
account_id: string;
|
|
272
|
-
tenant_id: string | null;
|
|
273
|
-
date: string;
|
|
274
|
-
api_requests: Generated<number>;
|
|
275
|
-
deliveries: Generated<number>;
|
|
276
|
-
streams_events_returned: Generated<number>;
|
|
277
|
-
index_decoded_events_returned: Generated<number>;
|
|
278
|
-
}
|
|
279
|
-
interface UsageSnapshotsTable {
|
|
280
|
-
id: Generated<string>;
|
|
281
|
-
account_id: string;
|
|
282
|
-
measured_at: Generated<Date>;
|
|
283
|
-
storage_bytes: Generated<number>;
|
|
284
|
-
}
|
|
285
|
-
interface AccountInsightsTable {
|
|
286
|
-
id: Generated<string>;
|
|
287
|
-
account_id: string;
|
|
288
|
-
category: string;
|
|
289
|
-
insight_type: string;
|
|
290
|
-
resource_id: string | null;
|
|
291
|
-
severity: string;
|
|
292
|
-
title: string;
|
|
293
|
-
body: string;
|
|
294
|
-
data: unknown;
|
|
295
|
-
dismissed_at: Date | null;
|
|
296
|
-
expires_at: Date | null;
|
|
297
|
-
created_at: Generated<Date>;
|
|
298
|
-
}
|
|
299
|
-
interface AccountAgentRunsTable {
|
|
300
|
-
id: Generated<string>;
|
|
301
|
-
account_id: string;
|
|
302
|
-
started_at: Generated<Date>;
|
|
303
|
-
completed_at: Date | null;
|
|
304
|
-
status: Generated<string>;
|
|
305
|
-
input_tokens: Generated<number>;
|
|
306
|
-
output_tokens: Generated<number>;
|
|
307
|
-
cost_usd: Generated<number>;
|
|
308
|
-
insights_created: Generated<number>;
|
|
309
|
-
error: string | null;
|
|
310
|
-
}
|
|
311
256
|
interface SubgraphProcessingStatsTable {
|
|
312
257
|
id: Generated<string>;
|
|
313
258
|
subgraph_name: string;
|
|
@@ -340,41 +285,6 @@ interface SubgraphHealthSnapshotsTable {
|
|
|
340
285
|
last_processed_block: number | null;
|
|
341
286
|
captured_at: Generated<Date>;
|
|
342
287
|
}
|
|
343
|
-
interface SubgraphUsageDailyTable {
|
|
344
|
-
subgraph_id: string;
|
|
345
|
-
date: string;
|
|
346
|
-
query_count: Generated<number>;
|
|
347
|
-
}
|
|
348
|
-
interface ProjectsTable {
|
|
349
|
-
id: Generated<string>;
|
|
350
|
-
name: string;
|
|
351
|
-
slug: string;
|
|
352
|
-
account_id: string;
|
|
353
|
-
settings: Generated<Record<string, unknown>>;
|
|
354
|
-
network: Generated<string>;
|
|
355
|
-
node_rpc: string | null;
|
|
356
|
-
created_at: Generated<Date>;
|
|
357
|
-
updated_at: Generated<Date>;
|
|
358
|
-
}
|
|
359
|
-
interface TeamMembersTable {
|
|
360
|
-
id: Generated<string>;
|
|
361
|
-
project_id: string;
|
|
362
|
-
account_id: string;
|
|
363
|
-
role: Generated<string>;
|
|
364
|
-
invited_by: string | null;
|
|
365
|
-
created_at: Generated<Date>;
|
|
366
|
-
}
|
|
367
|
-
interface TeamInvitationsTable {
|
|
368
|
-
id: Generated<string>;
|
|
369
|
-
project_id: string;
|
|
370
|
-
email: string;
|
|
371
|
-
role: Generated<string>;
|
|
372
|
-
token: string;
|
|
373
|
-
invited_by: string | null;
|
|
374
|
-
expires_at: Date;
|
|
375
|
-
accepted_at: Date | null;
|
|
376
|
-
created_at: Generated<Date>;
|
|
377
|
-
}
|
|
378
288
|
interface ProcessedStripeEventsTable {
|
|
379
289
|
event_id: string;
|
|
380
290
|
event_type: string;
|
|
@@ -811,6 +721,20 @@ interface StageFailuresTable {
|
|
|
811
721
|
resolved_at: Date | null;
|
|
812
722
|
retain_until: Generated<Date>;
|
|
813
723
|
}
|
|
724
|
+
/**
|
|
725
|
+
* The instance's declared scope — one row per network. `start_height` is what
|
|
726
|
+
* makes missing history below it deliberate rather than a gap.
|
|
727
|
+
*/
|
|
728
|
+
interface SyncScopesTable {
|
|
729
|
+
network: string;
|
|
730
|
+
start_height: number;
|
|
731
|
+
target_height: number | null;
|
|
732
|
+
bootstrap_source: BootstrapSource;
|
|
733
|
+
bootstrap_manifest_digest: string | null;
|
|
734
|
+
genesis_hash: string | null;
|
|
735
|
+
created_at: Generated<Date>;
|
|
736
|
+
updated_at: Generated<Date>;
|
|
737
|
+
}
|
|
814
738
|
interface Database {
|
|
815
739
|
blocks: BlocksTable;
|
|
816
740
|
transactions: TransactionsTable;
|
|
@@ -827,27 +751,14 @@ interface Database {
|
|
|
827
751
|
accounts: AccountsTable;
|
|
828
752
|
sessions: SessionsTable;
|
|
829
753
|
magic_links: MagicLinksTable;
|
|
830
|
-
claim_tokens: ClaimTokensTable;
|
|
831
|
-
usage_daily: UsageDailyTable;
|
|
832
|
-
usage_snapshots: UsageSnapshotsTable;
|
|
833
|
-
account_insights: AccountInsightsTable;
|
|
834
|
-
account_agent_runs: AccountAgentRunsTable;
|
|
835
754
|
subgraph_health_snapshots: SubgraphHealthSnapshotsTable;
|
|
836
755
|
subgraph_processing_stats: SubgraphProcessingStatsTable;
|
|
837
756
|
subgraph_table_snapshots: SubgraphTableSnapshotsTable;
|
|
838
757
|
subgraph_gaps: SubgraphGapsTable;
|
|
839
758
|
subgraph_operations: SubgraphOperationsTable;
|
|
840
|
-
subgraph_usage_daily: SubgraphUsageDailyTable;
|
|
841
|
-
projects: ProjectsTable;
|
|
842
|
-
team_members: TeamMembersTable;
|
|
843
|
-
team_invitations: TeamInvitationsTable;
|
|
844
759
|
processed_stripe_events: ProcessedStripeEventsTable;
|
|
845
|
-
tenants: TenantsTable;
|
|
846
|
-
tenant_usage_monthly: TenantUsageMonthlyTable;
|
|
847
|
-
tenant_compute_addons: TenantComputeAddonsTable;
|
|
848
760
|
account_spend_caps: AccountSpendCapsTable;
|
|
849
761
|
account_credits: AccountCreditsTable;
|
|
850
|
-
provisioning_audit_log: ProvisioningAuditLogTable;
|
|
851
762
|
subscriptions: SubscriptionsTable;
|
|
852
763
|
subscription_outbox: SubscriptionOutboxTable;
|
|
853
764
|
subscription_deliveries: SubscriptionDeliveriesTable;
|
|
@@ -876,6 +787,7 @@ interface Database {
|
|
|
876
787
|
chain_read_cache: ChainReadCacheTable;
|
|
877
788
|
pending_fork_blocks: PendingForkBlocksTable;
|
|
878
789
|
observer_journal: ObserverJournalTable;
|
|
790
|
+
sync_scopes: SyncScopesTable;
|
|
879
791
|
stage_registry: StageRegistryTable;
|
|
880
792
|
stage_runs: StageRunsTable;
|
|
881
793
|
stage_block_receipts: StageBlockReceiptsTable;
|
|
@@ -922,57 +834,6 @@ interface X402PaymentsTable {
|
|
|
922
834
|
* reconciler's heal path can never double-credit them. */
|
|
923
835
|
credited_at: Generated<Date> | null;
|
|
924
836
|
}
|
|
925
|
-
type TenantStatus = "provisioning" | "active" | "limit_warning" | "paused_limit" | "suspended" | "error" | "deleted";
|
|
926
|
-
interface TenantsTable {
|
|
927
|
-
id: Generated<string>;
|
|
928
|
-
account_id: string;
|
|
929
|
-
slug: string;
|
|
930
|
-
status: ColumnType<TenantStatus, TenantStatus | undefined, TenantStatus>;
|
|
931
|
-
plan: string;
|
|
932
|
-
cpus: ColumnType<number, number | string, number | string>;
|
|
933
|
-
memory_mb: number;
|
|
934
|
-
storage_limit_mb: number;
|
|
935
|
-
storage_used_mb: number | null;
|
|
936
|
-
pg_container_id: string | null;
|
|
937
|
-
api_container_id: string | null;
|
|
938
|
-
processor_container_id: string | null;
|
|
939
|
-
target_database_url_enc: Buffer;
|
|
940
|
-
tenant_jwt_secret_enc: Buffer;
|
|
941
|
-
anon_key_enc: Buffer;
|
|
942
|
-
service_key_enc: Buffer;
|
|
943
|
-
api_url_internal: string;
|
|
944
|
-
api_url_public: string;
|
|
945
|
-
suspended_at: Date | null;
|
|
946
|
-
last_health_check_at: Date | null;
|
|
947
|
-
last_active_at: Generated<Date>;
|
|
948
|
-
service_gen: Generated<number>;
|
|
949
|
-
anon_gen: Generated<number>;
|
|
950
|
-
project_id: string | null;
|
|
951
|
-
created_at: Generated<Date>;
|
|
952
|
-
updated_at: Generated<Date>;
|
|
953
|
-
}
|
|
954
|
-
interface TenantUsageMonthlyTable {
|
|
955
|
-
id: Generated<string>;
|
|
956
|
-
tenant_id: string;
|
|
957
|
-
period_month: Date;
|
|
958
|
-
storage_peak_mb: Generated<number>;
|
|
959
|
-
storage_avg_mb: Generated<number>;
|
|
960
|
-
storage_last_mb: Generated<number>;
|
|
961
|
-
measurements: Generated<number>;
|
|
962
|
-
first_at: Generated<Date>;
|
|
963
|
-
last_at: Generated<Date>;
|
|
964
|
-
}
|
|
965
|
-
interface TenantComputeAddonsTable {
|
|
966
|
-
id: Generated<string>;
|
|
967
|
-
tenant_id: string;
|
|
968
|
-
memory_mb_delta: Generated<number>;
|
|
969
|
-
cpu_delta: Generated<number | string>;
|
|
970
|
-
storage_mb_delta: Generated<number>;
|
|
971
|
-
effective_from: Generated<Date>;
|
|
972
|
-
effective_until: Date | null;
|
|
973
|
-
stripe_subscription_item_id: string | null;
|
|
974
|
-
created_at: Generated<Date>;
|
|
975
|
-
}
|
|
976
837
|
interface AccountSpendCapsTable {
|
|
977
838
|
account_id: string;
|
|
978
839
|
monthly_cap_cents: number | null;
|
|
@@ -996,20 +857,6 @@ interface AccountCreditsTable {
|
|
|
996
857
|
refill_last_at: Date | null;
|
|
997
858
|
updated_at: Generated<Date>;
|
|
998
859
|
}
|
|
999
|
-
type ProvisioningAuditEvent = "provision.start" | "provision.success" | "provision.failure" | "suspend" | "resume" | "resize" | "keys.rotate" | "bastion.key.upload" | "bastion.key.revoke" | "teardown";
|
|
1000
|
-
type ProvisioningAuditStatus = "ok" | "error";
|
|
1001
|
-
interface ProvisioningAuditLogTable {
|
|
1002
|
-
id: Generated<string>;
|
|
1003
|
-
tenant_id: string | null;
|
|
1004
|
-
tenant_slug: string | null;
|
|
1005
|
-
account_id: string | null;
|
|
1006
|
-
actor: string;
|
|
1007
|
-
event: ProvisioningAuditEvent;
|
|
1008
|
-
status: ProvisioningAuditStatus;
|
|
1009
|
-
detail: unknown | null;
|
|
1010
|
-
error: string | null;
|
|
1011
|
-
created_at: Generated<Date>;
|
|
1012
|
-
}
|
|
1013
860
|
type SubscriptionStatus = "active" | "paused" | "error";
|
|
1014
861
|
/** Polymorphic subscription mode: `subgraph` reacts to processed table rows;
|
|
1015
862
|
* `chain` reacts to raw chain events matched directly off the Index/Streams
|
|
@@ -155,13 +155,11 @@ declare function reportRuntimeStatus(input: {
|
|
|
155
155
|
coverage?: CoverageState | string
|
|
156
156
|
}): RuntimeStatusReport;
|
|
157
157
|
declare function actionFor(plane: StatusPlane, state: string): string;
|
|
158
|
-
|
|
159
|
-
* Backup bundle — consistent DB, pinned config, encrypted keys, handler
|
|
160
|
-
* manifests, and scope. Restore onto a wiped host must deep-verify green.
|
|
161
|
-
*/
|
|
158
|
+
declare const BACKUP_MANIFEST_VERSION = 1;
|
|
162
159
|
declare const BACKUP_PARTS: readonly ["db", "config", "keys", "handlers", "scope"];
|
|
163
160
|
type BackupPart = (typeof BACKUP_PARTS)[number];
|
|
164
161
|
type BackupManifest = {
|
|
162
|
+
schema_version: number
|
|
165
163
|
created_at: string
|
|
166
164
|
network: string
|
|
167
165
|
parts: BackupPart[]
|
|
@@ -170,34 +168,90 @@ type BackupManifest = {
|
|
|
170
168
|
from_height: number
|
|
171
169
|
to_height: number | null
|
|
172
170
|
}
|
|
171
|
+
db: {
|
|
172
|
+
file: string
|
|
173
|
+
sha256: string
|
|
174
|
+
bytes: number
|
|
175
|
+
format: string
|
|
176
|
+
} | null
|
|
177
|
+
/** Never the secrets themselves — only how to check them. */
|
|
178
|
+
secrets: {
|
|
179
|
+
file: string
|
|
180
|
+
encrypted: boolean
|
|
181
|
+
canary: string
|
|
182
|
+
} | null
|
|
183
|
+
signature?: string
|
|
184
|
+
key_id?: string
|
|
173
185
|
};
|
|
174
186
|
type BackupPlan = {
|
|
175
|
-
ok:
|
|
187
|
+
ok: true
|
|
176
188
|
manifest: BackupManifest
|
|
189
|
+
} | {
|
|
190
|
+
ok: false
|
|
177
191
|
reason: string
|
|
178
192
|
};
|
|
193
|
+
/**
|
|
194
|
+
* Validate a backup before any bytes are written. Refusing early is the whole
|
|
195
|
+
* point: a bundle that omits the keys looks like a backup and is not one.
|
|
196
|
+
*/
|
|
179
197
|
declare function planBackup(input: {
|
|
180
198
|
network: string
|
|
181
|
-
encryptedKeys: boolean
|
|
182
199
|
fromHeight: number
|
|
183
200
|
toHeight?: number | null
|
|
201
|
+
includeSecrets: boolean
|
|
202
|
+
secretsEncrypted: boolean
|
|
203
|
+
canary?: string
|
|
184
204
|
now?: string
|
|
185
205
|
}): BackupPlan;
|
|
186
|
-
|
|
206
|
+
/**
|
|
207
|
+
* Seal the canary under an EXPLICIT key.
|
|
208
|
+
*
|
|
209
|
+
* Deliberately not reusing `crypto/secrets.ts`: that module resolves the key
|
|
210
|
+
* from the ambient environment and, in OSS mode, generates and persists one as
|
|
211
|
+
* a side effect when it is missing. Calling it here would mean a backup could
|
|
212
|
+
* mint the very key it is supposed to be preserving.
|
|
213
|
+
*/
|
|
214
|
+
declare function sealKeyCanary(secretsKeyHex: string): string;
|
|
215
|
+
/** True only when `secretsKeyHex` is the key the canary was sealed with. */
|
|
216
|
+
declare function keyMatchesCanary(canaryBase64: string, secretsKeyHex: string): boolean;
|
|
217
|
+
/**
|
|
218
|
+
* Encrypt the secrets bundle under an operator passphrase.
|
|
219
|
+
* Layout: `salt(16) || iv(12) || authTag(16) || ciphertext`.
|
|
220
|
+
*/
|
|
221
|
+
declare function encryptBundle(plaintext: string, passphrase: string): Buffer;
|
|
222
|
+
declare function decryptBundle(envelope: Buffer, passphrase: string): string;
|
|
223
|
+
type RestorePrecheck = {
|
|
187
224
|
ok: true
|
|
188
|
-
applied: boolean
|
|
189
|
-
deep_green: boolean
|
|
190
225
|
} | {
|
|
191
226
|
ok: false
|
|
192
227
|
reason: string
|
|
228
|
+
fatal: boolean
|
|
193
229
|
};
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
230
|
+
/**
|
|
231
|
+
* Everything that must hold before a restore writes anything.
|
|
232
|
+
*
|
|
233
|
+
* `fatal` distinguishes "this bundle can never restore here" from "this needs
|
|
234
|
+
* an explicit override" — the caller surfaces them differently.
|
|
235
|
+
*/
|
|
236
|
+
declare function precheckRestore(input: {
|
|
237
|
+
manifest: BackupManifest
|
|
238
|
+
targetNetwork: string
|
|
239
|
+
targetIsEmpty: boolean
|
|
240
|
+
force: boolean
|
|
241
|
+
secretsKeyHex?: string
|
|
242
|
+
}): RestorePrecheck;
|
|
198
243
|
/**
|
|
199
244
|
* Upgrade contract — pin image, preflight schema/disk, backup first,
|
|
200
245
|
* migrate, health/verify, document rollback limits.
|
|
246
|
+
*
|
|
247
|
+
* PLANNER ONLY — `applyUpgrade` returns `{applied:true}` without pulling an
|
|
248
|
+
* image, running a preflight, or migrating anything. Nothing in the product
|
|
249
|
+
* calls it. The upgrade operators actually perform is `docker compose pull &&
|
|
250
|
+
* up -d`, with migrations applied at boot by the runtime entrypoint.
|
|
251
|
+
*
|
|
252
|
+
* Same caution as the sibling backup planner: this step list was published as
|
|
253
|
+
* an operator procedure in the self-host docs until 2026-08-15. Make it do the
|
|
254
|
+
* work before presenting it as one.
|
|
201
255
|
*/
|
|
202
256
|
declare const UPGRADE_STEPS: readonly ["pin", "preflight", "backup", "migrate", "health", "verify"];
|
|
203
257
|
type UpgradeStep = (typeof UPGRADE_STEPS)[number];
|
|
@@ -227,6 +281,13 @@ declare function applyUpgrade(plan: UpgradePlan, opts?: {
|
|
|
227
281
|
/**
|
|
228
282
|
* Resource guardrails — preflight RAM/disk/Postgres and estimate growth.
|
|
229
283
|
* Constrained fixtures fail early.
|
|
284
|
+
*
|
|
285
|
+
* The disk numbers here were wrong by 3-6x until 2026-08-15: they promised a
|
|
286
|
+
* full-history mainnet index would fit in 80 GB, and estimated growth at 1 GB
|
|
287
|
+
* per 100k blocks. The reference index measured 504 GB at height 8,771,873.
|
|
288
|
+
* An operator who sized a box from these figures would have filled the disk
|
|
289
|
+
* partway through their first bootstrap, so every constant below now cites what
|
|
290
|
+
* it was measured against.
|
|
230
291
|
*/
|
|
231
292
|
type ResourceSnapshot = {
|
|
232
293
|
ramMb: number
|
|
@@ -234,23 +295,81 @@ type ResourceSnapshot = {
|
|
|
234
295
|
postgresMaxConnections: number
|
|
235
296
|
postgresSharedBuffersMb?: number
|
|
236
297
|
};
|
|
298
|
+
type DiskEstimates = {
|
|
299
|
+
/** blocks + transactions + events, no decoded plane. */
|
|
300
|
+
diskGbPer100kBlocks: number
|
|
301
|
+
/** Same, plus a broad decoder set writing `decoded_events`. */
|
|
302
|
+
diskGbPer100kBlocksDecoded: number
|
|
303
|
+
};
|
|
237
304
|
type GuardrailResult = {
|
|
238
305
|
ok: true
|
|
239
|
-
estimates:
|
|
240
|
-
diskGbPer100kBlocks: number
|
|
241
|
-
}
|
|
306
|
+
estimates: DiskEstimates
|
|
242
307
|
} | {
|
|
243
308
|
ok: false
|
|
244
309
|
errors: string[]
|
|
245
310
|
};
|
|
311
|
+
type GuardrailNetwork = "mainnet" | "testnet" | "devnet";
|
|
246
312
|
declare const FLOORS: {
|
|
247
313
|
readonly appRamMb: 4096
|
|
248
314
|
readonly fullRamMb: 98304
|
|
315
|
+
/**
|
|
316
|
+
* Mainnet full history: 504 GB measured today, growing ~0.5 GB/day at the
|
|
317
|
+
* observed block rate. 600 leaves roughly six months of headroom, which is
|
|
318
|
+
* the point of a floor — a box that fits exactly today fails within weeks.
|
|
319
|
+
*/
|
|
320
|
+
readonly mainnetAppDiskGb: 600
|
|
321
|
+
/**
|
|
322
|
+
* Testnet/devnet carry a fraction of mainnet's history. Unmeasured; retained
|
|
323
|
+
* as the long-standing default rather than replaced with a fresh guess.
|
|
324
|
+
*/
|
|
249
325
|
readonly appDiskGb: 80
|
|
326
|
+
/**
|
|
327
|
+
* Bundled node on mainnet. The Stacks chainstate alone measured 1.3 TB on
|
|
328
|
+
* the reference node (2026-08-15), and the index adds ~500 GB; bitcoind is
|
|
329
|
+
* additional and not measured here. The previous 1.5 TB floor was below the
|
|
330
|
+
* two components we HAVE measured.
|
|
331
|
+
*/
|
|
332
|
+
readonly mainnetFullDiskGb: 2500
|
|
333
|
+
/** Bundled node, non-mainnet. Unmeasured; retained default. */
|
|
250
334
|
readonly fullDiskGb: 1500
|
|
251
335
|
readonly postgresMaxConnections: 50
|
|
252
336
|
};
|
|
253
|
-
|
|
337
|
+
/** The disk floor that applies to a given mode and network. */
|
|
338
|
+
declare function diskFloorGb(mode: "external" | "stacks" | "full", network: GuardrailNetwork): number;
|
|
339
|
+
/**
|
|
340
|
+
* A dimension the caller could not measure is absent, not zero. Skipping it
|
|
341
|
+
* keeps an unreadable `statfs` from presenting as a 0 GB disk and refusing a
|
|
342
|
+
* perfectly adequate box.
|
|
343
|
+
*/
|
|
344
|
+
declare function preflightResources(snap: Partial<ResourceSnapshot>, mode: "external" | "stacks" | "full", network?: GuardrailNetwork): GuardrailResult;
|
|
345
|
+
type MeasuredResources = {
|
|
346
|
+
snapshot: Partial<ResourceSnapshot>
|
|
347
|
+
/** Dimensions we could not read, with why. Never guessed at. */
|
|
348
|
+
unknown: string[]
|
|
349
|
+
};
|
|
350
|
+
declare function measureResources(input: {
|
|
351
|
+
dataDir: string
|
|
352
|
+
query?: (sql: string) => Promise<Array<Record<string, unknown>>>
|
|
353
|
+
}): Promise<MeasuredResources>;
|
|
354
|
+
declare const UNDERSIZED_OVERRIDE = "SECONDLAYER_ALLOW_UNDERSIZED";
|
|
355
|
+
type PreflightDecision = {
|
|
356
|
+
action: "pass" | "warn" | "refuse"
|
|
357
|
+
messages: string[]
|
|
358
|
+
};
|
|
359
|
+
declare function decidePreflight(input: {
|
|
360
|
+
measured: MeasuredResources
|
|
361
|
+
mode: "external" | "stacks" | "full"
|
|
362
|
+
network: GuardrailNetwork
|
|
363
|
+
env?: Record<string, string | undefined>
|
|
364
|
+
}): PreflightDecision;
|
|
365
|
+
/** Measure this box and decide. Returns the decision; the caller exits. */
|
|
366
|
+
declare function runPreflight(input: {
|
|
367
|
+
dataDir: string
|
|
368
|
+
mode: "external" | "stacks" | "full"
|
|
369
|
+
network: GuardrailNetwork
|
|
370
|
+
query?: (sql: string) => Promise<Array<Record<string, unknown>>>
|
|
371
|
+
env?: Record<string, string | undefined>
|
|
372
|
+
}): Promise<PreflightDecision>;
|
|
254
373
|
declare const MODULE_COMMANDS: Record<ModuleId, readonly string[]>;
|
|
255
374
|
declare function commandFor(id: ModuleId): readonly string[];
|
|
256
|
-
export {
|
|
375
|
+
export { sealKeyCanary, runPreflight, reportRuntimeStatus, preflightResources, precheckRestore, planUpgrade, planBackup, parseRuntimeConfig, migrateEmbedded, measureResources, keyMatchesCanary, isolateHandler, isModuleId, encryptBundle, emptyHealth, diskFloorGb, decryptBundle, decidePreflight, createSupervisor, createMemoryModule, createMemoryMigrationRunner, commandFor, applyUpgrade, actionFor, UpgradeStep, UpgradePlan, UPGRADE_STEPS, UNDERSIZED_OVERRIDE, SupervisorHealth, Supervisor, StatusPlane, STATUS_PLANES, SECRET_KEYS, RuntimeStatusReport, RuntimeNetwork, RuntimeModule, RuntimeConfig, RestorePrecheck, ResourceSnapshot, RequiredConfigKey, REQUIRED_KEYS, PreflightDecision, PlaneStatus, PUBLISHER_PROFILE, OPTIONAL_KEYS, NodeMode, NODE_MODES, NETWORKS, ModuleState, ModuleId, ModuleHealth, MigrationRunner, MeasuredResources, MODULE_STATES, MODULE_IDS, MODULE_COMMANDS, MIGRATION_LOCK_KEY, IsolationResult, IsolationOomError, IsolationNetworkError, IsolationLimits, IsolationKillError, IsolationFault, ISOLATION_FAULTS, GuardrailResult, GuardrailNetwork, FLOORS, EmbeddedMigration, DiskEstimates, DEFAULT_PROFILE, ConfigResult, BackupPlan, BackupPart, BackupManifest, BACKUP_PARTS, BACKUP_MANIFEST_VERSION };
|