@abloatai/transaction 0.47.0 → 0.48.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/src/footprint.ts CHANGED
@@ -51,25 +51,14 @@ export interface FootprintArtifact {
51
51
 
52
52
  // ── The names, for the code that creates and reads these objects ────────────
53
53
 
54
- /**
55
- * The publication Ablo's replication reads from. Constant by design: a
56
- * publication declares what streams, and several readers are meant to share one
57
- * (`publication_names` is a per-stream option, not slot state).
58
- */
54
+ /** Prefix used to derive a branch-scoped publication name. The exact unsuffixed
55
+ * name is retained only so `ablo connect scan` can identify an old installation. */
59
56
  export const ABLO_PUBLICATION = 'ablo_publication';
60
- /**
61
- * The replication slot that holds Ablo's position in the write-ahead log.
62
- *
63
- * Constant, and it should not be — a slot stores ONE position, so two
64
- * connections sharing this name compete for the same marker. It is why a
65
- * database can be connected to one plane at a time. ADR 0020 derives it per
66
- * connection; {@link isValidReplicationSlotName} is the check a derived name
67
- * has to pass.
68
- */
57
+ /** Prefix used to derive the branch-scoped replication slot. */
69
58
  export const ABLO_REPLICATION_SLOT = 'ablo_slot';
70
- /** The least-privilege login Ablo reads with. Per-connection under ADR 0020. */
59
+ /** Prefix used to derive the branch-scoped least-privilege replication login. */
71
60
  export const ABLO_REPLICATION_ROLE = 'ablo_replicator';
72
- /** The separate least-privilege login used only for row writes. */
61
+ /** Prefix used to derive the branch-scoped login used only for row writes. */
73
62
  export const ABLO_WRITE_ROLE = 'ablo_writer';
74
63
  /** The bookkeeping table that makes a retried write land once. */
75
64
  export const ABLO_IDEMPOTENCY_TABLE = 'ablo_idempotency';
@@ -90,15 +79,15 @@ export function isValidReplicationSlotName(name: string): boolean {
90
79
 
91
80
  // ── Per-connection names (ADR 0020) ─────────────────────────────────────────
92
81
 
93
- /** The immutable branch coordinates a connection is identified by. */
94
- export interface FootprintPlane {
82
+ /** The immutable branch coordinates that identify one customer Data Source. */
83
+ export interface DataSourceIdentity {
95
84
  readonly organizationId: string;
96
85
  readonly branchId: string;
97
86
  /** Omitted for the organization-default project. */
98
87
  readonly projectId?: string;
99
88
  }
100
89
 
101
- /** The names one connection owns. Nothing here is shared with another plane. */
90
+ /** The names one connection owns. Nothing here is shared with another Data Source. */
102
91
  export interface FootprintNames {
103
92
  readonly slot: string;
104
93
  readonly publication: string;
@@ -114,7 +103,7 @@ export interface FootprintNames {
114
103
  const SUFFIX_LENGTH = 16;
115
104
 
116
105
  /**
117
- * FNV-1a over the plane, in hex.
106
+ * FNV-1a over the Data Source identity, in hex.
118
107
  *
119
108
  * Deliberately not a cryptographic hash: this module is imported by the CLI,
120
109
  * which runs in environments without `node:crypto` guaranteed, and the property
@@ -123,13 +112,14 @@ const SUFFIX_LENGTH = 16;
123
112
  * over different seeds give the sixteen hex characters, which is ample for the
124
113
  * handful of planes any one database is ever connected to.
125
114
  */
126
- function planeDigest(plane: FootprintPlane): string {
115
+ function dataSourceDigest(identity: DataSourceIdentity): string {
127
116
  // The organization-default project may be omitted or repeated as the
128
117
  // organization id; both spell the same branch coordinates.
129
- const project = plane.projectId === plane.organizationId ? '' : (plane.projectId ?? '');
118
+ const project =
119
+ identity.projectId === identity.organizationId ? '' : (identity.projectId ?? '');
130
120
  // Delimit the coordinates. Concatenation alone makes structurally different
131
121
  // planes such as ("ab", "c") and ("a", "bc") hash the same input.
132
- const key = [plane.organizationId, project, plane.branchId].join('\0');
122
+ const key = [identity.organizationId, project, identity.branchId].join('\0');
133
123
 
134
124
  const round = (seed: number): string => {
135
125
  let hash = seed;
@@ -148,16 +138,15 @@ function planeDigest(plane: FootprintPlane): string {
148
138
  * The objects this connection owns, named so no other connection can claim them.
149
139
  *
150
140
  * A slot stores ONE position, so two connections sharing a name compete for the
151
- * same marker and Postgres reports nothing which is why the constants these
152
- * replace made a database connectable to one plane at a time. The publication
141
+ * same marker and Postgres reports nothing. The publication
153
142
  * and roles are derived from the same digest so a database's footprint reads as
154
143
  * one set per connection rather than a mix of shared and private objects.
155
144
  *
156
145
  * Stable: the same plane always derives the same names, so re-running setup is a
157
146
  * no-op rather than a second installation.
158
147
  */
159
- export function footprintNamesFor(plane: FootprintPlane): FootprintNames {
160
- const suffix = planeDigest(plane);
148
+ export function footprintNamesFor(identity: DataSourceIdentity): FootprintNames {
149
+ const suffix = dataSourceDigest(identity);
161
150
  const names: FootprintNames = {
162
151
  slot: `${ABLO_REPLICATION_SLOT}_${suffix}`,
163
152
  publication: `${ABLO_PUBLICATION}_${suffix}`,
@@ -644,7 +644,7 @@ export function abloOpenApi(options: SchemaToOpenApiOptions = {}): Json {
644
644
  '/v1/branches/{id}/status': {
645
645
  get: {
646
646
  tags: ['branches'],
647
- summary: 'Diagnose one branch plane',
647
+ summary: 'Diagnose one branch',
648
648
  description:
649
649
  'Returns branch lifecycle, active schema, compatibility with the parent schema, safe datasource coordinates, and readiness blockers.',
650
650
  parameters: [idParam()],
@@ -699,7 +699,7 @@ export function abloOpenApi(options: SchemaToOpenApiOptions = {}): Json {
699
699
  description:
700
700
  'One round trip per cadence for a worker holding many rows, instead of ' +
701
701
  'one per row. Takes only `ttl`; the leases are whichever ones your ' +
702
- 'credential holds on this plane.',
702
+ 'credential holds on this branch.',
703
703
  requestBody: optionalJsonBody(derive(claimHeartbeatRequestSchema, 'input')),
704
704
  responses: {
705
705
  '200': namedResp(
@@ -812,7 +812,7 @@ export function abloOpenApi(options: SchemaToOpenApiOptions = {}): Json {
812
812
  tags: ['schema'],
813
813
  summary: 'What the models look like',
814
814
  description:
815
- "The schema deployed on your credential's plane: every model with its " +
815
+ "The schema deployed on your credential's branch: every model with its " +
816
816
  'fields, their types, and its relations. Read this when you have no ' +
817
817
  'local schema declaration to read types from — it is what makes a ' +
818
818
  'field typo a local check rather than a rejected write. Each model ' +
@@ -835,7 +835,7 @@ export function abloOpenApi(options: SchemaToOpenApiOptions = {}): Json {
835
835
  'How a caller without a socket learns what its peers did. Omit ' +
836
836
  '`after` for the most recent entries, then copy each page\'s ' +
837
837
  '`next_cursor` back as `after` to walk forward. Scope is taken from ' +
838
- 'your key — organization, plane and sync groups — so a caller cannot ' +
838
+ 'your key — organization, branch and sync groups — so a caller cannot ' +
839
839
  'widen what it sees by asking.',
840
840
  parameters: queryParams(logQuerySchema),
841
841
  responses: {
@@ -192,5 +192,5 @@ export {
192
192
  type FootprintArtifact,
193
193
  type FootprintKind,
194
194
  type FootprintNames,
195
- type FootprintPlane,
195
+ type DataSourceIdentity,
196
196
  } from '../footprint.js';