@secondlayer/shared 7.7.0 → 7.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/dist/src/archive/derived-stage-report.d.ts +99 -0
  2. package/dist/src/archive/derived-stage-report.js +64 -0
  3. package/dist/src/archive/derived-stage-report.js.map +10 -0
  4. package/dist/src/archive/disk-guard.d.ts +46 -0
  5. package/dist/src/archive/disk-guard.js +69 -0
  6. package/dist/src/archive/disk-guard.js.map +10 -0
  7. package/dist/src/archive/key-registry.d.ts +52 -0
  8. package/dist/src/archive/key-registry.js +168 -0
  9. package/dist/src/archive/key-registry.js.map +11 -0
  10. package/dist/src/archive/per-height-digest.d.ts +99 -0
  11. package/dist/src/archive/per-height-digest.js +194 -0
  12. package/dist/src/archive/per-height-digest.js.map +11 -0
  13. package/dist/src/archive/progress.d.ts +36 -0
  14. package/dist/src/archive/progress.js +75 -0
  15. package/dist/src/archive/progress.js.map +10 -0
  16. package/dist/src/archive/range-digest.d.ts +7 -0
  17. package/dist/src/archive/semantic-digest-builder.d.ts +1094 -0
  18. package/dist/src/archive/semantic-digest-builder.js +302 -0
  19. package/dist/src/archive/semantic-digest-builder.js.map +11 -0
  20. package/dist/src/archive/semantic-digest.d.ts +131 -0
  21. package/dist/src/archive/semantic-digest.js +143 -0
  22. package/dist/src/archive/semantic-digest.js.map +10 -0
  23. package/dist/src/archive/status.d.ts +92 -0
  24. package/dist/src/archive/status.js +106 -0
  25. package/dist/src/archive/status.js.map +10 -0
  26. package/dist/src/db/index.d.ts +11 -1
  27. package/dist/src/db/index.js +26 -1
  28. package/dist/src/db/index.js.map +6 -5
  29. package/dist/src/db/queries/chain-reorgs.d.ts +7 -0
  30. package/dist/src/db/queries/chain-reorgs.js +25 -1
  31. package/dist/src/db/queries/chain-reorgs.js.map +6 -5
  32. package/dist/src/db/queries/contracts.d.ts +7 -0
  33. package/dist/src/db/queries/instance.d.ts +1038 -0
  34. package/dist/src/db/queries/instance.js +92 -0
  35. package/dist/src/db/queries/instance.js.map +10 -0
  36. package/dist/src/db/queries/integrity.d.ts +7 -0
  37. package/dist/src/db/queries/subgraph-gaps.d.ts +7 -0
  38. package/dist/src/db/queries/subgraph-operations.d.ts +7 -0
  39. package/dist/src/db/queries/subgraphs.d.ts +10 -1
  40. package/dist/src/db/queries/subgraphs.js +47 -23
  41. package/dist/src/db/queries/subgraphs.js.map +7 -7
  42. package/dist/src/db/queries/subscriptions.d.ts +7 -0
  43. package/dist/src/db/queries/subscriptions.js +47 -31
  44. package/dist/src/db/queries/subscriptions.js.map +5 -5
  45. package/dist/src/db/schema.d.ts +8 -1
  46. package/dist/src/index.d.ts +11 -1
  47. package/dist/src/index.js +26 -1
  48. package/dist/src/index.js.map +6 -5
  49. package/dist/src/node/client.d.ts +11 -1
  50. package/dist/src/node/client.js +42 -4
  51. package/dist/src/node/client.js.map +3 -3
  52. package/dist/src/node/local-client.d.ts +7 -0
  53. package/dist/src/node/nakamoto.d.ts +22 -7
  54. package/dist/src/node/nakamoto.js +46 -5
  55. package/dist/src/node/nakamoto.js.map +3 -3
  56. package/migrations/0115_instances.ts +33 -0
  57. package/package.json +38 -2
@@ -0,0 +1,92 @@
1
+ /**
2
+ * `status.json` — the archive's operational truth, published short-cache from
3
+ * verified state only.
4
+ *
5
+ * Everything else in the tree is immutable and signed, which makes it durable
6
+ * but silent: a consumer holding a valid manifest cannot tell whether it is
7
+ * current, three days behind, or the last thing published before an incident.
8
+ * This object answers that, and it is the only object allowed to say something
9
+ * unflattering.
10
+ *
11
+ * The distinction this file exists to protect:
12
+ *
13
+ * lagging → the archive trails the chain tip because it only publishes below
14
+ * the finality boundary. This is CORRECT and permanent. An archive
15
+ * that reported `stale` for its own finality lag would be crying
16
+ * wolf forever, and consumers would learn to ignore it.
17
+ * stale → publishing stopped. The lag exceeds what the finality rule can
18
+ * explain, so something is broken.
19
+ *
20
+ * `state` is derived from measurements, never asserted by the publisher, and
21
+ * every unhealthy state is reachable — an archive that can only report health
22
+ * is decoration.
23
+ */
24
+ declare const ARCHIVE_STATUS_SCHEMA_VERSION = 1;
25
+ type ArchiveState = "fresh" | "lagging" | "stale" | "gap" | "failed-audit" | "source-unavailable";
26
+ type ArchiveStatus = {
27
+ schema_version: typeof ARCHIVE_STATUS_SCHEMA_VERSION
28
+ network: string
29
+ state: ArchiveState
30
+ /** Human-facing one-liner explaining the state, including WHY. */
31
+ detail: string
32
+ generated_at: string
33
+ archive: {
34
+ snapshot_digest: string | null
35
+ coverage_to_block: number | null
36
+ promoted_at: string | null
37
+ signing_key_id: string | null
38
+ }
39
+ source: {
40
+ /** Chain tip as the publisher last observed it. Null when unreachable. */
41
+ tip_height: number | null
42
+ /** Highest height eligible to publish under the finality rule. */
43
+ finalized_height: number | null
44
+ }
45
+ lag: {
46
+ /** Behind the FINALIZED height — the number that indicates a problem. */
47
+ blocks_behind_finalized: number | null
48
+ /** Behind the raw chain tip — expected to be non-zero forever. */
49
+ blocks_behind_tip: number | null
50
+ seconds_since_promotion: number | null
51
+ }
52
+ audit: {
53
+ complete: boolean
54
+ checked_at: string
55
+ } | null
56
+ signature?: string
57
+ key_id?: string
58
+ };
59
+ type StatusInputs = {
60
+ network: string
61
+ snapshotDigest: string | null
62
+ coverageToBlock: number | null
63
+ promotedAt: string | null
64
+ signingKeyId: string | null
65
+ /** Null when the source could not be reached. */
66
+ sourceTipHeight: number | null
67
+ finalizedHeight: number | null
68
+ audit: {
69
+ complete: boolean
70
+ checkedAt: string
71
+ } | null
72
+ now: Date
73
+ /**
74
+ * How far behind the FINALIZED height the archive may fall before it is
75
+ * stale rather than merely lagging. Publishing one partition covers 50k
76
+ * blocks, so a healthy archive sits well inside this.
77
+ */
78
+ maxBlocksBehindFinalized?: number
79
+ /** How long since the last promotion before staleness, regardless of height. */
80
+ maxSecondsSincePromotion?: number
81
+ };
82
+ /**
83
+ * Derive status from measurements. Pure, so every state below is reachable in
84
+ * a test rather than only in production at 3am.
85
+ *
86
+ * Order matters: a failing audit outranks freshness, because an archive that
87
+ * is current and wrong is worse than one that is behind and correct.
88
+ */
89
+ declare function deriveArchiveStatus(inputs: StatusInputs): ArchiveStatus;
90
+ /** States a consumer should refuse to restore from. */
91
+ declare function isRestorable(state: ArchiveState): boolean;
92
+ export { isRestorable, deriveArchiveStatus, StatusInputs, ArchiveStatus, ArchiveState, ARCHIVE_STATUS_SCHEMA_VERSION };
@@ -0,0 +1,106 @@
1
+ import { createRequire } from "node:module";
2
+ var __defProp = Object.defineProperty;
3
+ var __returnValue = (v) => v;
4
+ function __exportSetter(name, newValue) {
5
+ this[name] = __returnValue.bind(null, newValue);
6
+ }
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, {
10
+ get: all[name],
11
+ enumerable: true,
12
+ configurable: true,
13
+ set: __exportSetter.bind(all, name)
14
+ });
15
+ };
16
+
17
+ // src/archive/status.ts
18
+ var ARCHIVE_STATUS_SCHEMA_VERSION = 1;
19
+ var DEFAULT_MAX_BLOCKS_BEHIND_FINALIZED = 60000;
20
+ var DEFAULT_MAX_SECONDS_SINCE_PROMOTION = 48 * 3600;
21
+ function deriveArchiveStatus(inputs) {
22
+ const maxBehind = inputs.maxBlocksBehindFinalized ?? DEFAULT_MAX_BLOCKS_BEHIND_FINALIZED;
23
+ const maxAge = inputs.maxSecondsSincePromotion ?? DEFAULT_MAX_SECONDS_SINCE_PROMOTION;
24
+ const secondsSincePromotion = inputs.promotedAt ? Math.max(0, Math.round((inputs.now.getTime() - Date.parse(inputs.promotedAt)) / 1000)) : null;
25
+ const behindFinalized = inputs.finalizedHeight !== null && inputs.coverageToBlock !== null ? Math.max(0, inputs.finalizedHeight - inputs.coverageToBlock) : null;
26
+ const behindTip = inputs.sourceTipHeight !== null && inputs.coverageToBlock !== null ? Math.max(0, inputs.sourceTipHeight - inputs.coverageToBlock) : null;
27
+ const base = {
28
+ schema_version: ARCHIVE_STATUS_SCHEMA_VERSION,
29
+ network: inputs.network,
30
+ generated_at: inputs.now.toISOString(),
31
+ archive: {
32
+ snapshot_digest: inputs.snapshotDigest,
33
+ coverage_to_block: inputs.coverageToBlock,
34
+ promoted_at: inputs.promotedAt,
35
+ signing_key_id: inputs.signingKeyId
36
+ },
37
+ source: {
38
+ tip_height: inputs.sourceTipHeight,
39
+ finalized_height: inputs.finalizedHeight
40
+ },
41
+ lag: {
42
+ blocks_behind_finalized: behindFinalized,
43
+ blocks_behind_tip: behindTip,
44
+ seconds_since_promotion: secondsSincePromotion
45
+ },
46
+ audit: inputs.audit ? { complete: inputs.audit.complete, checked_at: inputs.audit.checkedAt } : null
47
+ };
48
+ if (inputs.audit && !inputs.audit.complete) {
49
+ return {
50
+ ...base,
51
+ state: "failed-audit",
52
+ detail: `the canonical audit did not pass at ${inputs.audit.checkedAt}; this archive is not safe to restore from`
53
+ };
54
+ }
55
+ if (!inputs.snapshotDigest || inputs.coverageToBlock === null) {
56
+ return {
57
+ ...base,
58
+ state: "gap",
59
+ detail: "no snapshot is currently promoted"
60
+ };
61
+ }
62
+ if (inputs.sourceTipHeight === null || inputs.finalizedHeight === null) {
63
+ return {
64
+ ...base,
65
+ state: "source-unavailable",
66
+ detail: "the chain source could not be reached, so freshness cannot be determined"
67
+ };
68
+ }
69
+ if (secondsSincePromotion !== null && secondsSincePromotion > maxAge) {
70
+ return {
71
+ ...base,
72
+ state: "stale",
73
+ detail: `last promotion was ${Math.round(secondsSincePromotion / 3600)}h ago, beyond the ${Math.round(maxAge / 3600)}h freshness objective`
74
+ };
75
+ }
76
+ if (behindFinalized !== null && behindFinalized > maxBehind) {
77
+ return {
78
+ ...base,
79
+ state: "stale",
80
+ detail: `${behindFinalized} blocks behind the finalized height, beyond the ${maxBehind} threshold`
81
+ };
82
+ }
83
+ if (behindTip !== null && behindTip > 0) {
84
+ return {
85
+ ...base,
86
+ state: "lagging",
87
+ detail: `${behindTip} blocks behind the chain tip, which is expected: only heights below the finality boundary are published`
88
+ };
89
+ }
90
+ return {
91
+ ...base,
92
+ state: "fresh",
93
+ detail: "published through the finalized height"
94
+ };
95
+ }
96
+ function isRestorable(state) {
97
+ return state === "fresh" || state === "lagging";
98
+ }
99
+ export {
100
+ isRestorable,
101
+ deriveArchiveStatus,
102
+ ARCHIVE_STATUS_SCHEMA_VERSION
103
+ };
104
+
105
+ //# debugId=D9102A12541A66EA64756E2164756E21
106
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/archive/status.ts"],
4
+ "sourcesContent": [
5
+ "/**\n * `status.json` — the archive's operational truth, published short-cache from\n * verified state only.\n *\n * Everything else in the tree is immutable and signed, which makes it durable\n * but silent: a consumer holding a valid manifest cannot tell whether it is\n * current, three days behind, or the last thing published before an incident.\n * This object answers that, and it is the only object allowed to say something\n * unflattering.\n *\n * The distinction this file exists to protect:\n *\n * lagging → the archive trails the chain tip because it only publishes below\n * the finality boundary. This is CORRECT and permanent. An archive\n * that reported `stale` for its own finality lag would be crying\n * wolf forever, and consumers would learn to ignore it.\n * stale → publishing stopped. The lag exceeds what the finality rule can\n * explain, so something is broken.\n *\n * `state` is derived from measurements, never asserted by the publisher, and\n * every unhealthy state is reachable — an archive that can only report health\n * is decoration.\n */\n\nexport const ARCHIVE_STATUS_SCHEMA_VERSION = 1;\n\nexport type ArchiveState =\n\t| \"fresh\"\n\t| \"lagging\"\n\t| \"stale\"\n\t| \"gap\"\n\t| \"failed-audit\"\n\t| \"source-unavailable\";\n\nexport type ArchiveStatus = {\n\tschema_version: typeof ARCHIVE_STATUS_SCHEMA_VERSION;\n\tnetwork: string;\n\tstate: ArchiveState;\n\t/** Human-facing one-liner explaining the state, including WHY. */\n\tdetail: string;\n\tgenerated_at: string;\n\tarchive: {\n\t\tsnapshot_digest: string | null;\n\t\tcoverage_to_block: number | null;\n\t\tpromoted_at: string | null;\n\t\tsigning_key_id: string | null;\n\t};\n\tsource: {\n\t\t/** Chain tip as the publisher last observed it. Null when unreachable. */\n\t\ttip_height: number | null;\n\t\t/** Highest height eligible to publish under the finality rule. */\n\t\tfinalized_height: number | null;\n\t};\n\tlag: {\n\t\t/** Behind the FINALIZED height — the number that indicates a problem. */\n\t\tblocks_behind_finalized: number | null;\n\t\t/** Behind the raw chain tip — expected to be non-zero forever. */\n\t\tblocks_behind_tip: number | null;\n\t\tseconds_since_promotion: number | null;\n\t};\n\taudit: {\n\t\tcomplete: boolean;\n\t\tchecked_at: string;\n\t} | null;\n\tsignature?: string;\n\tkey_id?: string;\n};\n\nexport type StatusInputs = {\n\tnetwork: string;\n\tsnapshotDigest: string | null;\n\tcoverageToBlock: number | null;\n\tpromotedAt: string | null;\n\tsigningKeyId: string | null;\n\t/** Null when the source could not be reached. */\n\tsourceTipHeight: number | null;\n\tfinalizedHeight: number | null;\n\taudit: { complete: boolean; checkedAt: string } | null;\n\tnow: Date;\n\t/**\n\t * How far behind the FINALIZED height the archive may fall before it is\n\t * stale rather than merely lagging. Publishing one partition covers 50k\n\t * blocks, so a healthy archive sits well inside this.\n\t */\n\tmaxBlocksBehindFinalized?: number;\n\t/** How long since the last promotion before staleness, regardless of height. */\n\tmaxSecondsSincePromotion?: number;\n};\n\nconst DEFAULT_MAX_BLOCKS_BEHIND_FINALIZED = 60_000;\nconst DEFAULT_MAX_SECONDS_SINCE_PROMOTION = 48 * 3_600;\n\n/**\n * Derive status from measurements. Pure, so every state below is reachable in\n * a test rather than only in production at 3am.\n *\n * Order matters: a failing audit outranks freshness, because an archive that\n * is current and wrong is worse than one that is behind and correct.\n */\nexport function deriveArchiveStatus(inputs: StatusInputs): ArchiveStatus {\n\tconst maxBehind =\n\t\tinputs.maxBlocksBehindFinalized ?? DEFAULT_MAX_BLOCKS_BEHIND_FINALIZED;\n\tconst maxAge =\n\t\tinputs.maxSecondsSincePromotion ?? DEFAULT_MAX_SECONDS_SINCE_PROMOTION;\n\n\tconst secondsSincePromotion = inputs.promotedAt\n\t\t? Math.max(\n\t\t\t\t0,\n\t\t\t\tMath.round(\n\t\t\t\t\t(inputs.now.getTime() - Date.parse(inputs.promotedAt)) / 1000,\n\t\t\t\t),\n\t\t\t)\n\t\t: null;\n\n\tconst behindFinalized =\n\t\tinputs.finalizedHeight !== null && inputs.coverageToBlock !== null\n\t\t\t? Math.max(0, inputs.finalizedHeight - inputs.coverageToBlock)\n\t\t\t: null;\n\tconst behindTip =\n\t\tinputs.sourceTipHeight !== null && inputs.coverageToBlock !== null\n\t\t\t? Math.max(0, inputs.sourceTipHeight - inputs.coverageToBlock)\n\t\t\t: null;\n\n\tconst base = {\n\t\tschema_version:\n\t\t\tARCHIVE_STATUS_SCHEMA_VERSION as typeof ARCHIVE_STATUS_SCHEMA_VERSION,\n\t\tnetwork: inputs.network,\n\t\tgenerated_at: inputs.now.toISOString(),\n\t\tarchive: {\n\t\t\tsnapshot_digest: inputs.snapshotDigest,\n\t\t\tcoverage_to_block: inputs.coverageToBlock,\n\t\t\tpromoted_at: inputs.promotedAt,\n\t\t\tsigning_key_id: inputs.signingKeyId,\n\t\t},\n\t\tsource: {\n\t\t\ttip_height: inputs.sourceTipHeight,\n\t\t\tfinalized_height: inputs.finalizedHeight,\n\t\t},\n\t\tlag: {\n\t\t\tblocks_behind_finalized: behindFinalized,\n\t\t\tblocks_behind_tip: behindTip,\n\t\t\tseconds_since_promotion: secondsSincePromotion,\n\t\t},\n\t\taudit: inputs.audit\n\t\t\t? { complete: inputs.audit.complete, checked_at: inputs.audit.checkedAt }\n\t\t\t: null,\n\t};\n\n\t// A failed audit is the loudest signal: current-and-wrong beats behind-and-right.\n\tif (inputs.audit && !inputs.audit.complete) {\n\t\treturn {\n\t\t\t...base,\n\t\t\tstate: \"failed-audit\",\n\t\t\tdetail: `the canonical audit did not pass at ${inputs.audit.checkedAt}; this archive is not safe to restore from`,\n\t\t};\n\t}\n\n\tif (!inputs.snapshotDigest || inputs.coverageToBlock === null) {\n\t\treturn {\n\t\t\t...base,\n\t\t\tstate: \"gap\",\n\t\t\tdetail: \"no snapshot is currently promoted\",\n\t\t};\n\t}\n\n\t// Source unreachable: report the gap in KNOWLEDGE rather than guessing. The\n\t// archive may be perfectly healthy; we cannot currently say so.\n\tif (inputs.sourceTipHeight === null || inputs.finalizedHeight === null) {\n\t\treturn {\n\t\t\t...base,\n\t\t\tstate: \"source-unavailable\",\n\t\t\tdetail:\n\t\t\t\t\"the chain source could not be reached, so freshness cannot be determined\",\n\t\t};\n\t}\n\n\tif (secondsSincePromotion !== null && secondsSincePromotion > maxAge) {\n\t\treturn {\n\t\t\t...base,\n\t\t\tstate: \"stale\",\n\t\t\tdetail: `last promotion was ${Math.round(secondsSincePromotion / 3_600)}h ago, beyond the ${Math.round(maxAge / 3_600)}h freshness objective`,\n\t\t};\n\t}\n\n\tif (behindFinalized !== null && behindFinalized > maxBehind) {\n\t\treturn {\n\t\t\t...base,\n\t\t\tstate: \"stale\",\n\t\t\tdetail: `${behindFinalized} blocks behind the finalized height, beyond the ${maxBehind} threshold`,\n\t\t};\n\t}\n\n\t// Behind the tip but within the finality boundary — correct, permanent, and\n\t// explicitly NOT staleness.\n\tif (behindTip !== null && behindTip > 0) {\n\t\treturn {\n\t\t\t...base,\n\t\t\tstate: \"lagging\",\n\t\t\tdetail: `${behindTip} blocks behind the chain tip, which is expected: only heights below the finality boundary are published`,\n\t\t};\n\t}\n\n\treturn {\n\t\t...base,\n\t\tstate: \"fresh\",\n\t\tdetail: \"published through the finalized height\",\n\t};\n}\n\n/** States a consumer should refuse to restore from. */\nexport function isRestorable(state: ArchiveState): boolean {\n\treturn state === \"fresh\" || state === \"lagging\";\n}\n"
6
+ ],
7
+ "mappings": ";;;;;;;;;;;;;;;;;AAwBO,IAAM,gCAAgC;AAiE7C,IAAM,sCAAsC;AAC5C,IAAM,sCAAsC,KAAK;AAS1C,SAAS,mBAAmB,CAAC,QAAqC;AAAA,EACxE,MAAM,YACL,OAAO,4BAA4B;AAAA,EACpC,MAAM,SACL,OAAO,4BAA4B;AAAA,EAEpC,MAAM,wBAAwB,OAAO,aAClC,KAAK,IACL,GACA,KAAK,OACH,OAAO,IAAI,QAAQ,IAAI,KAAK,MAAM,OAAO,UAAU,KAAK,IAC1D,CACD,IACC;AAAA,EAEH,MAAM,kBACL,OAAO,oBAAoB,QAAQ,OAAO,oBAAoB,OAC3D,KAAK,IAAI,GAAG,OAAO,kBAAkB,OAAO,eAAe,IAC3D;AAAA,EACJ,MAAM,YACL,OAAO,oBAAoB,QAAQ,OAAO,oBAAoB,OAC3D,KAAK,IAAI,GAAG,OAAO,kBAAkB,OAAO,eAAe,IAC3D;AAAA,EAEJ,MAAM,OAAO;AAAA,IACZ,gBACC;AAAA,IACD,SAAS,OAAO;AAAA,IAChB,cAAc,OAAO,IAAI,YAAY;AAAA,IACrC,SAAS;AAAA,MACR,iBAAiB,OAAO;AAAA,MACxB,mBAAmB,OAAO;AAAA,MAC1B,aAAa,OAAO;AAAA,MACpB,gBAAgB,OAAO;AAAA,IACxB;AAAA,IACA,QAAQ;AAAA,MACP,YAAY,OAAO;AAAA,MACnB,kBAAkB,OAAO;AAAA,IAC1B;AAAA,IACA,KAAK;AAAA,MACJ,yBAAyB;AAAA,MACzB,mBAAmB;AAAA,MACnB,yBAAyB;AAAA,IAC1B;AAAA,IACA,OAAO,OAAO,QACX,EAAE,UAAU,OAAO,MAAM,UAAU,YAAY,OAAO,MAAM,UAAU,IACtE;AAAA,EACJ;AAAA,EAGA,IAAI,OAAO,SAAS,CAAC,OAAO,MAAM,UAAU;AAAA,IAC3C,OAAO;AAAA,SACH;AAAA,MACH,OAAO;AAAA,MACP,QAAQ,uCAAuC,OAAO,MAAM;AAAA,IAC7D;AAAA,EACD;AAAA,EAEA,IAAI,CAAC,OAAO,kBAAkB,OAAO,oBAAoB,MAAM;AAAA,IAC9D,OAAO;AAAA,SACH;AAAA,MACH,OAAO;AAAA,MACP,QAAQ;AAAA,IACT;AAAA,EACD;AAAA,EAIA,IAAI,OAAO,oBAAoB,QAAQ,OAAO,oBAAoB,MAAM;AAAA,IACvE,OAAO;AAAA,SACH;AAAA,MACH,OAAO;AAAA,MACP,QACC;AAAA,IACF;AAAA,EACD;AAAA,EAEA,IAAI,0BAA0B,QAAQ,wBAAwB,QAAQ;AAAA,IACrE,OAAO;AAAA,SACH;AAAA,MACH,OAAO;AAAA,MACP,QAAQ,sBAAsB,KAAK,MAAM,wBAAwB,IAAK,sBAAsB,KAAK,MAAM,SAAS,IAAK;AAAA,IACtH;AAAA,EACD;AAAA,EAEA,IAAI,oBAAoB,QAAQ,kBAAkB,WAAW;AAAA,IAC5D,OAAO;AAAA,SACH;AAAA,MACH,OAAO;AAAA,MACP,QAAQ,GAAG,kEAAkE;AAAA,IAC9E;AAAA,EACD;AAAA,EAIA,IAAI,cAAc,QAAQ,YAAY,GAAG;AAAA,IACxC,OAAO;AAAA,SACH;AAAA,MACH,OAAO;AAAA,MACP,QAAQ,GAAG;AAAA,IACZ;AAAA,EACD;AAAA,EAEA,OAAO;AAAA,OACH;AAAA,IACH,OAAO;AAAA,IACP,QAAQ;AAAA,EACT;AAAA;AAIM,SAAS,YAAY,CAAC,OAA8B;AAAA,EAC1D,OAAO,UAAU,WAAW,UAAU;AAAA;",
8
+ "debugId": "D9102A12541A66EA64756E2164756E21",
9
+ "names": []
10
+ }
@@ -209,6 +209,12 @@ interface ApiKeysTable {
209
209
  revoked_at: Date | null;
210
210
  created_at: Generated<Date>;
211
211
  }
212
+ /** Singleton self-host / publisher identity. Network is immutable. */
213
+ interface InstancesTable {
214
+ id: Generated<string>;
215
+ network: string;
216
+ created_at: Generated<Date>;
217
+ }
212
218
  interface AccountsTable {
213
219
  id: Generated<string>;
214
220
  /** NULL for unclaimed ghost accounts (anonymous self-serve keys). */
@@ -751,6 +757,7 @@ interface Database {
751
757
  contracts: ContractsTable;
752
758
  subgraphs: SubgraphsTable;
753
759
  api_keys: ApiKeysTable;
760
+ instances: InstancesTable;
754
761
  accounts: AccountsTable;
755
762
  sessions: SessionsTable;
756
763
  magic_links: MagicLinksTable;
@@ -2008,6 +2015,7 @@ declare const TABLE_TO_DB: {
2008
2015
  bns_marketplace_events: string
2009
2016
  bns_names: string
2010
2017
  bns_namespaces: string
2018
+ instances: string
2011
2019
  accounts: string
2012
2020
  api_keys: string
2013
2021
  sessions: string
@@ -2042,6 +2050,8 @@ declare const TABLE_TO_DB: {
2042
2050
  account_credits: string
2043
2051
  service_heartbeats: string
2044
2052
  };
2053
+ /** OSS: one application URL. SOURCE_/TARGET_ are hosted split only. */
2054
+ declare function applicationDatabaseUrl(): string;
2045
2055
  interface DbSplitStatus {
2046
2056
  /** "split" when source/target resolve to different DBs, else "single". */
2047
2057
  mode: "split" | "single";
@@ -2109,4 +2119,4 @@ declare function getRawClient(role?: "source" | "target"): ReturnType<typeof pos
2109
2119
  declare function getRawClientFor(url: string): ReturnType<typeof postgres>;
2110
2120
  /** Close all DB connection pools. Call in CLI commands to allow process exit. */
2111
2121
  declare function closeDb(): Promise<void>;
2112
- export { sql, setMigrationRole, parseJsonb, onControlPlane, onChainPlane, jsonb, getTargetDb, getSourceDb, getRawClientFor, getRawClient, getMigrationRole, getDbSplitStatus, getDb, closeDb, assertDbSplit, X402PaymentsTable, X402BalancesTable, UsageSnapshotsTable, UsageSnapshot, UsageDailyTable, UsageDaily, UpdateTransaction, UpdateTenantUsageMonthly, UpdateTenantComputeAddon, UpdateTenant, UpdateSubscriptionOutbox, UpdateSubscription, UpdateSubgraphOperation, UpdateSubgraph, UpdateProject, UpdateIndexProgress, UpdateEvent, UpdateContract, UpdateBlock, UpdateApiKey, UpdateAccountSpendCap, UpdateAccountCredits, TriggerEvaluatorStateTable, TriggerEvaluatorState, TransactionsTable, TransactionsArchiveTable, Transaction, TenantsTable, TenantUsageMonthlyTable, TenantUsageMonthly, TenantStatus, TenantComputeAddonsTable, TenantComputeAddon, Tenant, TeamMembersTable, TeamMember, TeamInvitationsTable, TeamInvitation, TABLE_TO_DB, SubscriptionsTable, SubscriptionStatus, SubscriptionRuntime, SubscriptionOutboxTable, SubscriptionOutbox, SubscriptionKind, SubscriptionFormat, SubscriptionDelivery, SubscriptionDeliveriesTable, Subscription, SubgraphsTable, SubgraphUsageDailyTable, SubgraphUsageDaily, SubgraphTableSnapshotsTable, SubgraphProcessingStatsTable, SubgraphOperationsTable, SubgraphOperationStatus, SubgraphOperationKind, SubgraphOperation, SubgraphHealthSnapshotsTable, SubgraphHealthSnapshot, SubgraphGapsTable, SubgraphGap, Subgraph, SessionsTable, Session, ServiceHeartbeatsTable, SbtcTokenEventsTable, SbtcTokenEventType, SbtcSupplySnapshotsTable, SbtcSettlementsTable, SbtcEventsTable, SbtcEventTopic, SOURCE_READ_TYPES, SOURCE_READ_PKS, SOURCE_READ_COLUMNS, ProvisioningAuditStatus, ProvisioningAuditLogTable, ProvisioningAuditLog, ProvisioningAuditEvent, ProjectsTable, Project, ProcessedStripeEventsTable, Pox5EventsTable, Pox5EventTopic, Pox4SignersDailyTable, Pox4FunctionName, Pox4CyclesDailyTable, Pox4CallsTable, PendingForkBlocksTable, OutboxStatus, ObserverJournalTable, ObserverJournalStatus, NumericAsText, MigrationRole, MempoolTransactionsTable, MempoolTransaction, MagicLinksTable, MagicLink, InsertTransaction, InsertTenantUsageMonthly, InsertTenantComputeAddon, InsertTenant, InsertTeamMember, InsertTeamInvitation, InsertSubscriptionOutbox, InsertSubscriptionDelivery, InsertSubscription, InsertSubgraphUsageDaily, InsertSubgraphOperation, InsertSubgraphHealthSnapshot, InsertSubgraphGap, InsertSubgraph, InsertSession, InsertProvisioningAuditLog, InsertProject, InsertMempoolTransaction, InsertMagicLink, InsertIndexProgress, InsertEvent, InsertContract, InsertClaimToken, InsertBlock, InsertApiKey, InsertAccountSpendCap, InsertAccountInsight, InsertAccountCredits, InsertAccountAgentRun, InsertAccount, IndexProgressTable, IndexProgress, IndexPrimaryKey, IndexColumnType, IndexColumn, EventsTable, EventsArchiveTable, Event, DecoderCheckpointsTable, DecodedEventsTable, DeadLetterEventsTable, DbSplitStatus, DbReadRow, DbPlane, Database, ContractsTable, Contract, ClaimTokensTable, ClaimToken, ChainReorgsTable, ChainReadCacheTable, BurnBlockRewardsTable, BurnBlockRewardSlotsTable, BnsNamespacesTable, BnsNamespaceEventsTable, BnsNamespaceEventStatus, BnsNamesTable, BnsNameEventsTable, BnsNameEventTopic, BnsMarketplaceEventsTable, BnsMarketplaceAction, BlocksTable, Block, ApiKeysTable, ApiKey, AccountsTable, AccountSpendCapsTable, AccountSpendCap, AccountInsightsTable, AccountInsight, AccountCreditsTable, AccountCredits, AccountAgentRunsTable, AccountAgentRun, Account };
2122
+ export { sql, setMigrationRole, parseJsonb, onControlPlane, onChainPlane, jsonb, getTargetDb, getSourceDb, getRawClientFor, getRawClient, getMigrationRole, getDbSplitStatus, getDb, closeDb, assertDbSplit, applicationDatabaseUrl, X402PaymentsTable, X402BalancesTable, UsageSnapshotsTable, UsageSnapshot, UsageDailyTable, UsageDaily, UpdateTransaction, UpdateTenantUsageMonthly, UpdateTenantComputeAddon, UpdateTenant, UpdateSubscriptionOutbox, UpdateSubscription, UpdateSubgraphOperation, UpdateSubgraph, UpdateProject, UpdateIndexProgress, UpdateEvent, UpdateContract, UpdateBlock, UpdateApiKey, UpdateAccountSpendCap, UpdateAccountCredits, TriggerEvaluatorStateTable, TriggerEvaluatorState, TransactionsTable, TransactionsArchiveTable, Transaction, TenantsTable, TenantUsageMonthlyTable, TenantUsageMonthly, TenantStatus, TenantComputeAddonsTable, TenantComputeAddon, Tenant, TeamMembersTable, TeamMember, TeamInvitationsTable, TeamInvitation, TABLE_TO_DB, SubscriptionsTable, SubscriptionStatus, SubscriptionRuntime, SubscriptionOutboxTable, SubscriptionOutbox, SubscriptionKind, SubscriptionFormat, SubscriptionDelivery, SubscriptionDeliveriesTable, Subscription, SubgraphsTable, SubgraphUsageDailyTable, SubgraphUsageDaily, SubgraphTableSnapshotsTable, SubgraphProcessingStatsTable, SubgraphOperationsTable, SubgraphOperationStatus, SubgraphOperationKind, SubgraphOperation, SubgraphHealthSnapshotsTable, SubgraphHealthSnapshot, SubgraphGapsTable, SubgraphGap, Subgraph, SessionsTable, Session, ServiceHeartbeatsTable, SbtcTokenEventsTable, SbtcTokenEventType, SbtcSupplySnapshotsTable, SbtcSettlementsTable, SbtcEventsTable, SbtcEventTopic, SOURCE_READ_TYPES, SOURCE_READ_PKS, SOURCE_READ_COLUMNS, ProvisioningAuditStatus, ProvisioningAuditLogTable, ProvisioningAuditLog, ProvisioningAuditEvent, ProjectsTable, Project, ProcessedStripeEventsTable, Pox5EventsTable, Pox5EventTopic, Pox4SignersDailyTable, Pox4FunctionName, Pox4CyclesDailyTable, Pox4CallsTable, PendingForkBlocksTable, OutboxStatus, ObserverJournalTable, ObserverJournalStatus, NumericAsText, MigrationRole, MempoolTransactionsTable, MempoolTransaction, MagicLinksTable, MagicLink, InstancesTable, InsertTransaction, InsertTenantUsageMonthly, InsertTenantComputeAddon, InsertTenant, InsertTeamMember, InsertTeamInvitation, InsertSubscriptionOutbox, InsertSubscriptionDelivery, InsertSubscription, InsertSubgraphUsageDaily, InsertSubgraphOperation, InsertSubgraphHealthSnapshot, InsertSubgraphGap, InsertSubgraph, InsertSession, InsertProvisioningAuditLog, InsertProject, InsertMempoolTransaction, InsertMagicLink, InsertIndexProgress, InsertEvent, InsertContract, InsertClaimToken, InsertBlock, InsertApiKey, InsertAccountSpendCap, InsertAccountInsight, InsertAccountCredits, InsertAccountAgentRun, InsertAccount, IndexProgressTable, IndexProgress, IndexPrimaryKey, IndexColumnType, IndexColumn, EventsTable, EventsArchiveTable, Event, DecoderCheckpointsTable, DecodedEventsTable, DeadLetterEventsTable, DbSplitStatus, DbReadRow, DbPlane, Database, ContractsTable, Contract, ClaimTokensTable, ClaimToken, ChainReorgsTable, ChainReadCacheTable, BurnBlockRewardsTable, BurnBlockRewardSlotsTable, BnsNamespacesTable, BnsNamespaceEventsTable, BnsNamespaceEventStatus, BnsNamesTable, BnsNameEventsTable, BnsNameEventTopic, BnsMarketplaceEventsTable, BnsMarketplaceAction, BlocksTable, Block, ApiKeysTable, ApiKey, AccountsTable, AccountSpendCapsTable, AccountSpendCap, AccountInsightsTable, AccountInsight, AccountCreditsTable, AccountCredits, AccountAgentRunsTable, AccountAgentRun, Account };
@@ -138,6 +138,22 @@ class Logger {
138
138
  }
139
139
  var logger = new Logger;
140
140
 
141
+ // src/mode.ts
142
+ var VALID_MODES = ["oss", "platform"];
143
+ function getInstanceMode() {
144
+ const raw = process.env.INSTANCE_MODE?.trim().toLowerCase();
145
+ if (raw && VALID_MODES.includes(raw)) {
146
+ return raw;
147
+ }
148
+ return "oss";
149
+ }
150
+ function isPlatformMode() {
151
+ return getInstanceMode() === "platform";
152
+ }
153
+ function isOssMode() {
154
+ return getInstanceMode() === "oss";
155
+ }
156
+
141
157
  // src/db/jsonb.ts
142
158
  import { sql } from "kysely";
143
159
  function jsonb(value) {
@@ -723,6 +739,7 @@ var TABLE_TO_DB = {
723
739
  bns_marketplace_events: "source",
724
740
  bns_names: "source",
725
741
  bns_namespaces: "source",
742
+ instances: "target",
726
743
  accounts: "target",
727
744
  api_keys: "target",
728
745
  sessions: "target",
@@ -785,10 +802,17 @@ function evictIfNeeded() {
785
802
  const evicted = lruEntry;
786
803
  evicted.db.destroy().catch(() => {}).then(() => evicted.rawClient.end({ timeout: 5 })).catch(() => {});
787
804
  }
805
+ function applicationDatabaseUrl() {
806
+ return process.env.DATABASE_URL || DEFAULT_URL;
807
+ }
788
808
  function resolveSourceUrl() {
809
+ if (!isPlatformMode())
810
+ return applicationDatabaseUrl();
789
811
  return process.env.SOURCE_DATABASE_URL || process.env.DATABASE_URL || DEFAULT_URL;
790
812
  }
791
813
  function resolveTargetUrl() {
814
+ if (!isPlatformMode())
815
+ return applicationDatabaseUrl();
792
816
  return process.env.TARGET_DATABASE_URL || process.env.DATABASE_URL || DEFAULT_URL;
793
817
  }
794
818
  function describeDbUrl(url) {
@@ -943,11 +967,12 @@ export {
943
967
  getDb,
944
968
  closeDb,
945
969
  assertDbSplit,
970
+ applicationDatabaseUrl,
946
971
  TABLE_TO_DB,
947
972
  SOURCE_READ_TYPES,
948
973
  SOURCE_READ_PKS,
949
974
  SOURCE_READ_COLUMNS
950
975
  };
951
976
 
952
- //# debugId=37AABDB3C4D0230C64756E2164756E21
977
+ //# debugId=BB27A04E8664D30164756E2164756E21
953
978
  //# sourceMappingURL=index.js.map