@tiangong-lca/cli 0.1.8 → 0.1.9
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 +13 -3
- package/dist/src/cli.d.ts +2 -0
- package/dist/src/cli.js +43 -1
- package/dist/src/cli.js.map +1 -1
- package/dist/src/lib/dataset-support-cache.d.ts +48 -0
- package/dist/src/lib/dataset-support-cache.js +265 -0
- package/dist/src/lib/dataset-support-cache.js.map +1 -0
- package/dist/src/lib/supabase-data-api-contract.d.ts +4 -4
- package/dist/src/lib/supabase-data-api-contract.js +2 -0
- package/dist/src/lib/supabase-data-api-contract.js.map +1 -1
- package/package.json +4 -2
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { type ResolveAuthIdentitySession } from './auth-identity-receipt.js';
|
|
2
|
+
import type { FetchLike } from './http.js';
|
|
3
|
+
import { type DatasetMaintenanceSnapshotCompleteness } from './dataset-maintenance-pagination.js';
|
|
4
|
+
declare const TABLES: readonly ['flowproperties', 'unitgroups'];
|
|
5
|
+
type Table = (typeof TABLES)[number];
|
|
6
|
+
export type RunDatasetSupportCacheExportOptions = {
|
|
7
|
+
outDir: string;
|
|
8
|
+
env: NodeJS.ProcessEnv;
|
|
9
|
+
fetchImpl: FetchLike;
|
|
10
|
+
cliVersion: string;
|
|
11
|
+
stateCodes?: number[];
|
|
12
|
+
pageSize?: number;
|
|
13
|
+
timeoutMs?: number;
|
|
14
|
+
expectedProjectRef?: string;
|
|
15
|
+
expectedUserId?: string;
|
|
16
|
+
now?: Date;
|
|
17
|
+
resolveSessionImpl?: ResolveAuthIdentitySession;
|
|
18
|
+
monotonicNow?: () => number;
|
|
19
|
+
};
|
|
20
|
+
export type DatasetSupportCacheExportReport = {
|
|
21
|
+
schema_version: 1;
|
|
22
|
+
command: 'dataset support-cache export';
|
|
23
|
+
status: 'completed';
|
|
24
|
+
remote_write_mode: 'read-only';
|
|
25
|
+
captured_at_utc: string;
|
|
26
|
+
project_ref: string;
|
|
27
|
+
account: {
|
|
28
|
+
user_id: string;
|
|
29
|
+
session_source: string;
|
|
30
|
+
};
|
|
31
|
+
filters: {
|
|
32
|
+
state_codes: number[];
|
|
33
|
+
requested_page_size: number;
|
|
34
|
+
};
|
|
35
|
+
snapshot: {
|
|
36
|
+
status: 'observed-stable';
|
|
37
|
+
transactional_snapshot: false;
|
|
38
|
+
observations: 2;
|
|
39
|
+
};
|
|
40
|
+
completeness: DatasetMaintenanceSnapshotCompleteness<Table>[];
|
|
41
|
+
tables: Record<Table, {
|
|
42
|
+
rows: number;
|
|
43
|
+
sha256: string;
|
|
44
|
+
}>;
|
|
45
|
+
artifacts: Record<Table | 'identity' | 'report', string>;
|
|
46
|
+
};
|
|
47
|
+
export declare function runDatasetSupportCacheExport(options: RunDatasetSupportCacheExportOptions): Promise<DatasetSupportCacheExportReport>;
|
|
48
|
+
export {};
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
// data-api-relations: flowproperties, unitgroups
|
|
2
|
+
import { createHash } from 'node:crypto';
|
|
3
|
+
import { lstatSync, mkdirSync, renameSync, rmSync, writeFileSync } from 'node:fs';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { runAuthIdentityReceipt, } from './auth-identity-receipt.js';
|
|
6
|
+
import { CliError } from './errors.js';
|
|
7
|
+
import { buildSnapshotCompleteness, fetchCompletePostgrestPages, parseExactContentRange, } from './dataset-maintenance-pagination.js';
|
|
8
|
+
import { buildSupabaseAuthHeaders, deriveSupabaseRestBaseUrl, requireSupabaseRestRuntime, } from './supabase-client.js';
|
|
9
|
+
import { applyDataApiProfileHeaders, buildDataApiUrl, resolveDataApiCapabilityFromUrl, } from './supabase-data-api-contract.js';
|
|
10
|
+
import { resolveSupabaseUserSession, } from './supabase-session.js';
|
|
11
|
+
const TABLES = ['flowproperties', 'unitgroups'];
|
|
12
|
+
const MAX_ROWS = 100_000;
|
|
13
|
+
const MAX_PAGES = 1_000;
|
|
14
|
+
const MAX_RESPONSE_BYTES = 8 * 1024 * 1024;
|
|
15
|
+
const MAX_TOTAL_BYTES = 64 * 1024 * 1024;
|
|
16
|
+
const MAX_DURATION_MS = 120_000;
|
|
17
|
+
function fail(code, message, exitCode = 1) {
|
|
18
|
+
throw new CliError(message, { code: `DATASET_SUPPORT_CACHE_${code}`, exitCode });
|
|
19
|
+
}
|
|
20
|
+
function integer(value, minimum, maximum, label) {
|
|
21
|
+
if (!Number.isSafeInteger(value) || value < minimum || value > maximum)
|
|
22
|
+
fail('OPTION_INVALID', `${label} is outside the supported integer range.`, 2);
|
|
23
|
+
return value;
|
|
24
|
+
}
|
|
25
|
+
function object(value) {
|
|
26
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
27
|
+
}
|
|
28
|
+
function rowsFrom(value, states) {
|
|
29
|
+
if (!Array.isArray(value))
|
|
30
|
+
fail('ROWS_INVALID', 'Support response must be an array.');
|
|
31
|
+
return value.map((row) => {
|
|
32
|
+
if (!object(row) ||
|
|
33
|
+
typeof row.id !== 'string' ||
|
|
34
|
+
!row.id.trim() ||
|
|
35
|
+
typeof row.version !== 'string' ||
|
|
36
|
+
!row.version.trim() ||
|
|
37
|
+
!Number.isSafeInteger(row.state_code) ||
|
|
38
|
+
!object(row.json))
|
|
39
|
+
fail('ROWS_INVALID', 'Support response contains an invalid row.');
|
|
40
|
+
if (!states.includes(row.state_code))
|
|
41
|
+
fail('STATE_FENCE_VIOLATION', 'Support response escaped the requested state filters.');
|
|
42
|
+
return {
|
|
43
|
+
id: row.id,
|
|
44
|
+
version: row.version,
|
|
45
|
+
state_code: row.state_code,
|
|
46
|
+
json: row.json,
|
|
47
|
+
};
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
async function readBounded(response) {
|
|
51
|
+
if (Number(response.headers.get('content-length')) > MAX_RESPONSE_BYTES)
|
|
52
|
+
fail('BYTE_LIMIT', 'Support response exceeded the byte limit.');
|
|
53
|
+
if (!response.body) {
|
|
54
|
+
const text = await response.text();
|
|
55
|
+
if (Buffer.byteLength(text) > MAX_RESPONSE_BYTES)
|
|
56
|
+
fail('BYTE_LIMIT', 'Support response exceeded the byte limit.');
|
|
57
|
+
return text;
|
|
58
|
+
}
|
|
59
|
+
const reader = response.body.getReader();
|
|
60
|
+
const chunks = [];
|
|
61
|
+
let bytes = 0;
|
|
62
|
+
try {
|
|
63
|
+
for (;;) {
|
|
64
|
+
const chunk = await reader.read();
|
|
65
|
+
if (chunk.done)
|
|
66
|
+
break;
|
|
67
|
+
bytes += chunk.value.byteLength;
|
|
68
|
+
if (bytes > MAX_RESPONSE_BYTES) {
|
|
69
|
+
await reader.cancel();
|
|
70
|
+
fail('BYTE_LIMIT', 'Support response exceeded the byte limit.');
|
|
71
|
+
}
|
|
72
|
+
chunks.push(chunk.value);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
finally {
|
|
76
|
+
reader.releaseLock();
|
|
77
|
+
}
|
|
78
|
+
return Buffer.concat(chunks).toString('utf8');
|
|
79
|
+
}
|
|
80
|
+
function rowBytes(rows) {
|
|
81
|
+
return rows.map((row) => JSON.stringify(row) + '\n').join('');
|
|
82
|
+
}
|
|
83
|
+
function digest(bytes) {
|
|
84
|
+
return createHash('sha256').update(bytes).digest('hex');
|
|
85
|
+
}
|
|
86
|
+
export async function runDatasetSupportCacheExport(options) {
|
|
87
|
+
if (!options.outDir.trim())
|
|
88
|
+
fail('OUT_DIR_REQUIRED', 'A fresh --out-dir is required.', 2);
|
|
89
|
+
const outDir = path.resolve(options.outDir);
|
|
90
|
+
if (lstatSync(outDir, { throwIfNoEntry: false }))
|
|
91
|
+
fail('OUTPUT_EXISTS', 'Support export output already exists.', 2);
|
|
92
|
+
const pageSize = integer(options.pageSize ?? 1000, 1, 5000, 'Page size');
|
|
93
|
+
const timeoutMs = integer(options.timeoutMs ?? 10000, 1, MAX_DURATION_MS, 'Timeout');
|
|
94
|
+
const states = [...new Set(options.stateCodes ?? [100])].sort((a, b) => a - b);
|
|
95
|
+
if (!states.length)
|
|
96
|
+
fail('OPTION_INVALID', 'At least one state code is required.', 2);
|
|
97
|
+
states.forEach((state) => integer(state, -2147483648, 2147483647, 'State code'));
|
|
98
|
+
const runtime = requireSupabaseRestRuntime(options.env);
|
|
99
|
+
if (runtime.authMode !== 'oauth')
|
|
100
|
+
fail('OAUTH_REQUIRED', 'Support export requires a CLI OAuth session.', 2);
|
|
101
|
+
const clock = options.monotonicNow ?? (() => performance.now());
|
|
102
|
+
const started = clock();
|
|
103
|
+
const overall = AbortSignal.timeout(MAX_DURATION_MS);
|
|
104
|
+
const fetchImpl = (url, init = {}) => options.fetchImpl(url, {
|
|
105
|
+
...init,
|
|
106
|
+
signal: AbortSignal.any([overall, init.signal ?? AbortSignal.timeout(timeoutMs)]),
|
|
107
|
+
});
|
|
108
|
+
const resolver = options.resolveSessionImpl ?? resolveSupabaseUserSession;
|
|
109
|
+
const holder = {};
|
|
110
|
+
const identity = await runAuthIdentityReceipt({
|
|
111
|
+
env: options.env,
|
|
112
|
+
fetchImpl,
|
|
113
|
+
cliVersion: options.cliVersion,
|
|
114
|
+
expectedProjectRef: options.expectedProjectRef,
|
|
115
|
+
expectedUserId: options.expectedUserId,
|
|
116
|
+
timeoutMs,
|
|
117
|
+
now: options.now,
|
|
118
|
+
resolveSessionImpl: async (request) => {
|
|
119
|
+
holder.session = await resolver(request);
|
|
120
|
+
return holder.session;
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
// The canonical identity runner resolves a session before it can return this receipt.
|
|
124
|
+
const session = holder.session;
|
|
125
|
+
const restBase = deriveSupabaseRestBaseUrl(runtime.apiBaseUrl);
|
|
126
|
+
let totalBytes = 0;
|
|
127
|
+
const observations = [];
|
|
128
|
+
for (let observation = 0; observation < 2; observation += 1) {
|
|
129
|
+
const collected = {};
|
|
130
|
+
const results = [];
|
|
131
|
+
for (const table of TABLES) {
|
|
132
|
+
let pages = 0;
|
|
133
|
+
try {
|
|
134
|
+
const result = await fetchCompletePostgrestPages({
|
|
135
|
+
table,
|
|
136
|
+
requestedPageSize: pageSize,
|
|
137
|
+
rowIdentity: (row) => `${row.id}@${row.version}`,
|
|
138
|
+
fetchPage: async (offset) => {
|
|
139
|
+
if (++pages > MAX_PAGES)
|
|
140
|
+
fail('PAGE_LIMIT', 'Support export exceeded the page limit.');
|
|
141
|
+
if (clock() - started >= MAX_DURATION_MS)
|
|
142
|
+
fail('TIME_LIMIT', 'Support export exceeded the operation deadline.');
|
|
143
|
+
const url = new URL(buildDataApiUrl(restBase, { kind: 'relation', name: table }));
|
|
144
|
+
url.searchParams.set('select', 'id,version,state_code,json');
|
|
145
|
+
url.searchParams.set('state_code', `in.(${states.join(',')})`);
|
|
146
|
+
url.searchParams.set('order', 'id.asc,version.asc');
|
|
147
|
+
url.searchParams.set('limit', String(pageSize));
|
|
148
|
+
url.searchParams.set('offset', String(offset));
|
|
149
|
+
const headers = applyDataApiProfileHeaders({
|
|
150
|
+
...buildSupabaseAuthHeaders(runtime.publishableKey, session.accessToken),
|
|
151
|
+
Prefer: 'count=exact',
|
|
152
|
+
}, resolveDataApiCapabilityFromUrl({ url: url.toString(), method: 'GET' }), 'GET');
|
|
153
|
+
const response = await fetchImpl(url.toString(), {
|
|
154
|
+
method: 'GET',
|
|
155
|
+
headers,
|
|
156
|
+
redirect: 'error',
|
|
157
|
+
});
|
|
158
|
+
if (!response.ok)
|
|
159
|
+
fail('READ_FAILED', 'Support export request was rejected.');
|
|
160
|
+
const range = response.headers.get('content-range');
|
|
161
|
+
if (parseExactContentRange(range).total > MAX_ROWS)
|
|
162
|
+
fail('ROW_LIMIT', 'Support export exceeded the row limit.');
|
|
163
|
+
const text = await readBounded(response);
|
|
164
|
+
totalBytes += Buffer.byteLength(text);
|
|
165
|
+
if (totalBytes > MAX_TOTAL_BYTES)
|
|
166
|
+
fail('BYTE_LIMIT', 'Support export exceeded the total byte limit.');
|
|
167
|
+
let value;
|
|
168
|
+
try {
|
|
169
|
+
value = JSON.parse(text);
|
|
170
|
+
}
|
|
171
|
+
catch {
|
|
172
|
+
fail('INVALID_JSON', 'Support response is not valid JSON.');
|
|
173
|
+
}
|
|
174
|
+
return {
|
|
175
|
+
rows: rowsFrom(value, states),
|
|
176
|
+
source_url: url.toString(),
|
|
177
|
+
content_range: range,
|
|
178
|
+
};
|
|
179
|
+
},
|
|
180
|
+
});
|
|
181
|
+
collected[table] = result.rows;
|
|
182
|
+
results.push({ table, completeness: result.completeness });
|
|
183
|
+
}
|
|
184
|
+
catch (error) {
|
|
185
|
+
if (error instanceof CliError && error.code.startsWith('DATASET_SUPPORT_CACHE_'))
|
|
186
|
+
throw error;
|
|
187
|
+
if (error instanceof CliError && error.code === 'DATASET_MAINTENANCE_SNAPSHOT_INCOMPLETE')
|
|
188
|
+
fail('SNAPSHOT_INCOMPLETE', 'Support pagination completeness could not be proven.');
|
|
189
|
+
fail('READ_FAILED', 'Support export request failed.');
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
observations.push({
|
|
193
|
+
rows: collected,
|
|
194
|
+
completeness: buildSnapshotCompleteness({
|
|
195
|
+
tables: TABLES,
|
|
196
|
+
requestedPageSize: pageSize,
|
|
197
|
+
results,
|
|
198
|
+
}),
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
const first = observations[0];
|
|
202
|
+
const second = observations[1];
|
|
203
|
+
const bytes = {
|
|
204
|
+
flowproperties: rowBytes(first.rows.flowproperties),
|
|
205
|
+
unitgroups: rowBytes(first.rows.unitgroups),
|
|
206
|
+
};
|
|
207
|
+
for (const table of TABLES) {
|
|
208
|
+
if (digest(bytes[table]) !== digest(rowBytes(second.rows[table])))
|
|
209
|
+
fail('CONTENT_DRIFT', 'Support rows changed between observations.');
|
|
210
|
+
}
|
|
211
|
+
const artifacts = {
|
|
212
|
+
flowproperties: path.join(outDir, 'flowproperties.jsonl'),
|
|
213
|
+
unitgroups: path.join(outDir, 'unitgroups.jsonl'),
|
|
214
|
+
identity: path.join(outDir, 'identity-receipt.json'),
|
|
215
|
+
report: path.join(outDir, 'export-report.json'),
|
|
216
|
+
};
|
|
217
|
+
const report = {
|
|
218
|
+
schema_version: 1,
|
|
219
|
+
command: 'dataset support-cache export',
|
|
220
|
+
status: 'completed',
|
|
221
|
+
remote_write_mode: 'read-only',
|
|
222
|
+
captured_at_utc: identity.captured_at_utc,
|
|
223
|
+
project_ref: identity.project.project_ref,
|
|
224
|
+
account: { user_id: identity.identity.user_id, session_source: identity.session.source },
|
|
225
|
+
filters: { state_codes: states, requested_page_size: pageSize },
|
|
226
|
+
snapshot: { status: 'observed-stable', transactional_snapshot: false, observations: 2 },
|
|
227
|
+
completeness: observations.map((item) => item.completeness),
|
|
228
|
+
tables: {
|
|
229
|
+
flowproperties: {
|
|
230
|
+
rows: first.rows.flowproperties.length,
|
|
231
|
+
sha256: digest(bytes.flowproperties),
|
|
232
|
+
},
|
|
233
|
+
unitgroups: { rows: first.rows.unitgroups.length, sha256: digest(bytes.unitgroups) },
|
|
234
|
+
},
|
|
235
|
+
artifacts,
|
|
236
|
+
};
|
|
237
|
+
if (clock() - started >= MAX_DURATION_MS)
|
|
238
|
+
fail('TIME_LIMIT', 'Support export exceeded the operation deadline.');
|
|
239
|
+
try {
|
|
240
|
+
mkdirSync(path.dirname(outDir), { recursive: true, mode: 0o700 });
|
|
241
|
+
mkdirSync(outDir, { mode: 0o700 });
|
|
242
|
+
}
|
|
243
|
+
catch (error) {
|
|
244
|
+
// Reservation failure must never clean another writer's output.
|
|
245
|
+
if (error.code === 'EEXIST')
|
|
246
|
+
fail('OUTPUT_EXISTS', 'Support export output already exists.', 2);
|
|
247
|
+
fail('ARTIFACT_WRITE_FAILED', 'Support export could not reserve its output directory.');
|
|
248
|
+
}
|
|
249
|
+
try {
|
|
250
|
+
for (const table of TABLES)
|
|
251
|
+
writeFileSync(artifacts[table], bytes[table], { flag: 'wx', mode: 0o600 });
|
|
252
|
+
writeFileSync(artifacts.identity, JSON.stringify(identity) + '\n', { flag: 'wx', mode: 0o600 });
|
|
253
|
+
writeFileSync(artifacts.report + '.tmp', JSON.stringify(report) + '\n', {
|
|
254
|
+
flag: 'wx',
|
|
255
|
+
mode: 0o600,
|
|
256
|
+
});
|
|
257
|
+
renameSync(artifacts.report + '.tmp', artifacts.report);
|
|
258
|
+
}
|
|
259
|
+
catch {
|
|
260
|
+
rmSync(outDir, { recursive: true, force: true });
|
|
261
|
+
fail('ARTIFACT_WRITE_FAILED', 'Support export could not publish its completion report.');
|
|
262
|
+
}
|
|
263
|
+
return report;
|
|
264
|
+
}
|
|
265
|
+
//# sourceMappingURL=dataset-support-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dataset-support-cache.js","sourceRoot":"","sources":["../../../src/lib/dataset-support-cache.ts"],"names":[],"mappings":"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","sourcesContent":["// data-api-relations: flowproperties, unitgroups\nimport { createHash } from 'node:crypto';\nimport { lstatSync, mkdirSync, renameSync, rmSync, writeFileSync } from 'node:fs';\nimport path from 'node:path';\nimport {\n runAuthIdentityReceipt,\n type ResolveAuthIdentitySession,\n} from './auth-identity-receipt.js';\nimport { CliError } from './errors.js';\nimport type { FetchLike, ResponseLike } from './http.js';\nimport {\n buildSnapshotCompleteness,\n fetchCompletePostgrestPages,\n parseExactContentRange,\n type DatasetMaintenanceSnapshotCompleteness,\n} from './dataset-maintenance-pagination.js';\nimport {\n buildSupabaseAuthHeaders,\n deriveSupabaseRestBaseUrl,\n requireSupabaseRestRuntime,\n} from './supabase-client.js';\nimport {\n applyDataApiProfileHeaders,\n buildDataApiUrl,\n resolveDataApiCapabilityFromUrl,\n} from './supabase-data-api-contract.js';\nimport {\n resolveSupabaseUserSession,\n type ResolvedSupabaseUserSession,\n} from './supabase-session.js';\n\nconst TABLES = ['flowproperties', 'unitgroups'] as const;\ntype Table = (typeof TABLES)[number];\ntype Row = { id: string; version: string; state_code: number; json: Record<string, unknown> };\nconst MAX_ROWS = 100_000;\nconst MAX_PAGES = 1_000;\nconst MAX_RESPONSE_BYTES = 8 * 1024 * 1024;\nconst MAX_TOTAL_BYTES = 64 * 1024 * 1024;\nconst MAX_DURATION_MS = 120_000;\n\nexport type RunDatasetSupportCacheExportOptions = {\n outDir: string;\n env: NodeJS.ProcessEnv;\n fetchImpl: FetchLike;\n cliVersion: string;\n stateCodes?: number[];\n pageSize?: number;\n timeoutMs?: number;\n expectedProjectRef?: string;\n expectedUserId?: string;\n now?: Date;\n resolveSessionImpl?: ResolveAuthIdentitySession;\n monotonicNow?: () => number;\n};\n\nexport type DatasetSupportCacheExportReport = {\n schema_version: 1;\n command: 'dataset support-cache export';\n status: 'completed';\n remote_write_mode: 'read-only';\n captured_at_utc: string;\n project_ref: string;\n account: { user_id: string; session_source: string };\n filters: { state_codes: number[]; requested_page_size: number };\n snapshot: { status: 'observed-stable'; transactional_snapshot: false; observations: 2 };\n completeness: DatasetMaintenanceSnapshotCompleteness<Table>[];\n tables: Record<Table, { rows: number; sha256: string }>;\n artifacts: Record<Table | 'identity' | 'report', string>;\n};\n\nfunction fail(code: string, message: string, exitCode = 1): never {\n throw new CliError(message, { code: `DATASET_SUPPORT_CACHE_${code}`, exitCode });\n}\n\nfunction integer(value: number, minimum: number, maximum: number, label: string): number {\n if (!Number.isSafeInteger(value) || value < minimum || value > maximum)\n fail('OPTION_INVALID', `${label} is outside the supported integer range.`, 2);\n return value;\n}\n\nfunction object(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction rowsFrom(value: unknown, states: readonly number[]): Row[] {\n if (!Array.isArray(value)) fail('ROWS_INVALID', 'Support response must be an array.');\n return value.map((row: unknown) => {\n if (\n !object(row) ||\n typeof row.id !== 'string' ||\n !row.id.trim() ||\n typeof row.version !== 'string' ||\n !row.version.trim() ||\n !Number.isSafeInteger(row.state_code) ||\n !object(row.json)\n )\n fail('ROWS_INVALID', 'Support response contains an invalid row.');\n if (!states.includes(row.state_code as number))\n fail('STATE_FENCE_VIOLATION', 'Support response escaped the requested state filters.');\n return {\n id: row.id,\n version: row.version,\n state_code: row.state_code as number,\n json: row.json,\n };\n });\n}\n\nasync function readBounded(response: ResponseLike): Promise<string> {\n if (Number(response.headers.get('content-length')) > MAX_RESPONSE_BYTES)\n fail('BYTE_LIMIT', 'Support response exceeded the byte limit.');\n if (!response.body) {\n const text = await response.text();\n if (Buffer.byteLength(text) > MAX_RESPONSE_BYTES)\n fail('BYTE_LIMIT', 'Support response exceeded the byte limit.');\n return text;\n }\n const reader = response.body.getReader();\n const chunks: Uint8Array[] = [];\n let bytes = 0;\n try {\n for (;;) {\n const chunk = await reader.read();\n if (chunk.done) break;\n bytes += chunk.value.byteLength;\n if (bytes > MAX_RESPONSE_BYTES) {\n await reader.cancel();\n fail('BYTE_LIMIT', 'Support response exceeded the byte limit.');\n }\n chunks.push(chunk.value);\n }\n } finally {\n reader.releaseLock();\n }\n return Buffer.concat(chunks).toString('utf8');\n}\n\nfunction rowBytes(rows: Row[]): string {\n return rows.map((row) => JSON.stringify(row) + '\\n').join('');\n}\n\nfunction digest(bytes: string): string {\n return createHash('sha256').update(bytes).digest('hex');\n}\n\nexport async function runDatasetSupportCacheExport(\n options: RunDatasetSupportCacheExportOptions,\n): Promise<DatasetSupportCacheExportReport> {\n if (!options.outDir.trim()) fail('OUT_DIR_REQUIRED', 'A fresh --out-dir is required.', 2);\n const outDir = path.resolve(options.outDir);\n if (lstatSync(outDir, { throwIfNoEntry: false }))\n fail('OUTPUT_EXISTS', 'Support export output already exists.', 2);\n const pageSize = integer(options.pageSize ?? 1000, 1, 5000, 'Page size');\n const timeoutMs = integer(options.timeoutMs ?? 10000, 1, MAX_DURATION_MS, 'Timeout');\n const states = [...new Set(options.stateCodes ?? [100])].sort((a, b) => a - b);\n if (!states.length) fail('OPTION_INVALID', 'At least one state code is required.', 2);\n states.forEach((state) => integer(state, -2147483648, 2147483647, 'State code'));\n const runtime = requireSupabaseRestRuntime(options.env);\n if (runtime.authMode !== 'oauth')\n fail('OAUTH_REQUIRED', 'Support export requires a CLI OAuth session.', 2);\n const clock = options.monotonicNow ?? (() => performance.now());\n const started = clock();\n const overall = AbortSignal.timeout(MAX_DURATION_MS);\n const fetchImpl: FetchLike = (url, init = {}) =>\n options.fetchImpl(url, {\n ...init,\n signal: AbortSignal.any([overall, init.signal ?? AbortSignal.timeout(timeoutMs)]),\n });\n const resolver = options.resolveSessionImpl ?? resolveSupabaseUserSession;\n const holder: { session?: ResolvedSupabaseUserSession } = {};\n const identity = await runAuthIdentityReceipt({\n env: options.env,\n fetchImpl,\n cliVersion: options.cliVersion,\n expectedProjectRef: options.expectedProjectRef,\n expectedUserId: options.expectedUserId,\n timeoutMs,\n now: options.now,\n resolveSessionImpl: async (request) => {\n holder.session = await resolver(request);\n return holder.session;\n },\n });\n // The canonical identity runner resolves a session before it can return this receipt.\n const session = holder.session!;\n const restBase = deriveSupabaseRestBaseUrl(runtime.apiBaseUrl);\n let totalBytes = 0;\n const observations: Array<{\n rows: Record<Table, Row[]>;\n completeness: DatasetMaintenanceSnapshotCompleteness<Table>;\n }> = [];\n for (let observation = 0; observation < 2; observation += 1) {\n const collected = {} as Record<Table, Row[]>;\n const results = [];\n for (const table of TABLES) {\n let pages = 0;\n try {\n const result = await fetchCompletePostgrestPages({\n table,\n requestedPageSize: pageSize,\n rowIdentity: (row: Row) => `${row.id}@${row.version}`,\n fetchPage: async (offset) => {\n if (++pages > MAX_PAGES) fail('PAGE_LIMIT', 'Support export exceeded the page limit.');\n if (clock() - started >= MAX_DURATION_MS)\n fail('TIME_LIMIT', 'Support export exceeded the operation deadline.');\n const url = new URL(buildDataApiUrl(restBase, { kind: 'relation', name: table }));\n url.searchParams.set('select', 'id,version,state_code,json');\n url.searchParams.set('state_code', `in.(${states.join(',')})`);\n url.searchParams.set('order', 'id.asc,version.asc');\n url.searchParams.set('limit', String(pageSize));\n url.searchParams.set('offset', String(offset));\n const headers = applyDataApiProfileHeaders(\n {\n ...buildSupabaseAuthHeaders(runtime.publishableKey, session.accessToken),\n Prefer: 'count=exact',\n },\n resolveDataApiCapabilityFromUrl({ url: url.toString(), method: 'GET' }),\n 'GET',\n );\n const response = await fetchImpl(url.toString(), {\n method: 'GET',\n headers,\n redirect: 'error',\n });\n if (!response.ok) fail('READ_FAILED', 'Support export request was rejected.');\n const range = response.headers.get('content-range');\n if (parseExactContentRange(range).total > MAX_ROWS)\n fail('ROW_LIMIT', 'Support export exceeded the row limit.');\n const text = await readBounded(response);\n totalBytes += Buffer.byteLength(text);\n if (totalBytes > MAX_TOTAL_BYTES)\n fail('BYTE_LIMIT', 'Support export exceeded the total byte limit.');\n let value: unknown;\n try {\n value = JSON.parse(text);\n } catch {\n fail('INVALID_JSON', 'Support response is not valid JSON.');\n }\n return {\n rows: rowsFrom(value, states),\n source_url: url.toString(),\n content_range: range,\n };\n },\n });\n collected[table] = result.rows;\n results.push({ table, completeness: result.completeness });\n } catch (error) {\n if (error instanceof CliError && error.code.startsWith('DATASET_SUPPORT_CACHE_'))\n throw error;\n if (error instanceof CliError && error.code === 'DATASET_MAINTENANCE_SNAPSHOT_INCOMPLETE')\n fail('SNAPSHOT_INCOMPLETE', 'Support pagination completeness could not be proven.');\n fail('READ_FAILED', 'Support export request failed.');\n }\n }\n observations.push({\n rows: collected,\n completeness: buildSnapshotCompleteness({\n tables: TABLES,\n requestedPageSize: pageSize,\n results,\n }),\n });\n }\n const first = observations[0]!;\n const second = observations[1]!;\n const bytes = {\n flowproperties: rowBytes(first.rows.flowproperties),\n unitgroups: rowBytes(first.rows.unitgroups),\n };\n for (const table of TABLES) {\n if (digest(bytes[table]) !== digest(rowBytes(second.rows[table])))\n fail('CONTENT_DRIFT', 'Support rows changed between observations.');\n }\n const artifacts = {\n flowproperties: path.join(outDir, 'flowproperties.jsonl'),\n unitgroups: path.join(outDir, 'unitgroups.jsonl'),\n identity: path.join(outDir, 'identity-receipt.json'),\n report: path.join(outDir, 'export-report.json'),\n };\n const report: DatasetSupportCacheExportReport = {\n schema_version: 1,\n command: 'dataset support-cache export',\n status: 'completed',\n remote_write_mode: 'read-only',\n captured_at_utc: identity.captured_at_utc,\n project_ref: identity.project.project_ref,\n account: { user_id: identity.identity.user_id, session_source: identity.session.source },\n filters: { state_codes: states, requested_page_size: pageSize },\n snapshot: { status: 'observed-stable', transactional_snapshot: false, observations: 2 },\n completeness: observations.map((item) => item.completeness),\n tables: {\n flowproperties: {\n rows: first.rows.flowproperties.length,\n sha256: digest(bytes.flowproperties),\n },\n unitgroups: { rows: first.rows.unitgroups.length, sha256: digest(bytes.unitgroups) },\n },\n artifacts,\n };\n if (clock() - started >= MAX_DURATION_MS)\n fail('TIME_LIMIT', 'Support export exceeded the operation deadline.');\n try {\n mkdirSync(path.dirname(outDir), { recursive: true, mode: 0o700 });\n mkdirSync(outDir, { mode: 0o700 });\n } catch (error) {\n // Reservation failure must never clean another writer's output.\n if ((error as NodeJS.ErrnoException).code === 'EEXIST')\n fail('OUTPUT_EXISTS', 'Support export output already exists.', 2);\n fail('ARTIFACT_WRITE_FAILED', 'Support export could not reserve its output directory.');\n }\n try {\n for (const table of TABLES)\n writeFileSync(artifacts[table], bytes[table], { flag: 'wx', mode: 0o600 });\n writeFileSync(artifacts.identity, JSON.stringify(identity) + '\\n', { flag: 'wx', mode: 0o600 });\n writeFileSync(artifacts.report + '.tmp', JSON.stringify(report) + '\\n', {\n flag: 'wx',\n mode: 0o600,\n });\n renameSync(artifacts.report + '.tmp', artifacts.report);\n } catch {\n rmSync(outDir, { recursive: true, force: true });\n fail('ARTIFACT_WRITE_FAILED', 'Support export could not publish its completion report.');\n }\n return report;\n}\n"]}
|
|
@@ -7,14 +7,14 @@ export declare const CORE_PUBLIC_RELATIONS: readonly ['contacts', 'flowpropertie
|
|
|
7
7
|
export type CorePublicRelation = (typeof CORE_PUBLIC_RELATIONS)[number];
|
|
8
8
|
export declare const DATA_API_RELATION_CONSUMERS: {
|
|
9
9
|
readonly contacts: readonly ["src/lib/dataset-save-draft-run.ts", "src/lib/dataset-remote-verify.ts", "src/lib/dataset-maintenance-remote.ts", "src/lib/process-refresh-references.ts", "src/lib/dataset-maintenance-clear-account.ts"];
|
|
10
|
-
readonly flowproperties: readonly ["src/lib/dataset-save-draft-run.ts", "src/lib/dataset-remote-verify.ts", "src/lib/dataset-maintenance-remote.ts", "src/lib/dataset-maintenance-flow-identity-capture.ts", "src/lib/process-refresh-references.ts"];
|
|
10
|
+
readonly flowproperties: readonly ["src/lib/dataset-support-cache.ts", "src/lib/dataset-save-draft-run.ts", "src/lib/dataset-remote-verify.ts", "src/lib/dataset-maintenance-remote.ts", "src/lib/dataset-maintenance-flow-identity-capture.ts", "src/lib/process-refresh-references.ts"];
|
|
11
11
|
readonly flows: readonly ["src/lib/flow-read.ts", "src/lib/flow-list.ts", "src/lib/flow-publish-version.ts", "src/lib/dataset-save-draft-run.ts", "src/lib/dataset-remote-verify.ts", "src/lib/dataset-maintenance-remote.ts", "src/lib/dataset-maintenance-flow-identity-capture.ts", "src/lib/process-refresh-references.ts", "src/lib/dataset-maintenance-clear-account.ts"];
|
|
12
12
|
readonly ilcd: readonly [];
|
|
13
13
|
readonly lciamethods: readonly ["src/lib/dataset-remote-verify.ts", "src/lib/dataset-maintenance-remote.ts", "src/lib/process-refresh-references.ts"];
|
|
14
14
|
readonly lifecyclemodels: readonly ["src/lib/lifecyclemodel-bundle-save.ts", "src/lib/process-dedup-review.ts", "src/lib/dataset-remote-verify.ts", "src/lib/dataset-maintenance-remote.ts", "src/lib/supabase-json-ordered-write.ts", "src/lib/dataset-maintenance-clear-account.ts"];
|
|
15
15
|
readonly processes: readonly ["src/lib/process-get.ts", "src/lib/process-list.ts", "src/lib/process-save-draft.ts", "src/lib/process-scope-statistics.ts", "src/lib/process-dedup-review.ts", "src/lib/process-refresh-references.ts", "src/lib/dataset-save-draft-run.ts", "src/lib/dataset-remote-verify.ts", "src/lib/dataset-maintenance-remote.ts", "src/lib/supabase-json-ordered-write.ts", "src/lib/supabase-rest.ts", "src/lib/dataset-maintenance-clear-account.ts"];
|
|
16
16
|
readonly sources: readonly ["src/lib/dataset-save-draft-run.ts", "src/lib/dataset-remote-verify.ts", "src/lib/dataset-maintenance-remote.ts", "src/lib/supabase-json-ordered-write.ts", "src/lib/process-refresh-references.ts", "src/lib/dataset-maintenance-clear-account.ts"];
|
|
17
|
-
readonly unitgroups: readonly ["src/lib/dataset-save-draft-run.ts", "src/lib/dataset-remote-verify.ts", "src/lib/dataset-maintenance-remote.ts", "src/lib/dataset-maintenance-flow-identity-capture.ts", "src/lib/process-refresh-references.ts"];
|
|
17
|
+
readonly unitgroups: readonly ["src/lib/dataset-support-cache.ts", "src/lib/dataset-save-draft-run.ts", "src/lib/dataset-remote-verify.ts", "src/lib/dataset-maintenance-remote.ts", "src/lib/dataset-maintenance-flow-identity-capture.ts", "src/lib/process-refresh-references.ts"];
|
|
18
18
|
};
|
|
19
19
|
export declare const DATA_API_RPC_TARGETS: {
|
|
20
20
|
readonly cmd_dataset_alias_execution_admit_guarded: {
|
|
@@ -127,14 +127,14 @@ export declare const DATA_API_CONTRACT: {
|
|
|
127
127
|
readonly corePublicRelations: readonly ["contacts", "flowproperties", "flows", "ilcd", "lciamethods", "lifecyclemodels", "processes", "sources", "unitgroups"];
|
|
128
128
|
readonly relationConsumers: {
|
|
129
129
|
readonly contacts: readonly ["src/lib/dataset-save-draft-run.ts", "src/lib/dataset-remote-verify.ts", "src/lib/dataset-maintenance-remote.ts", "src/lib/process-refresh-references.ts", "src/lib/dataset-maintenance-clear-account.ts"];
|
|
130
|
-
readonly flowproperties: readonly ["src/lib/dataset-save-draft-run.ts", "src/lib/dataset-remote-verify.ts", "src/lib/dataset-maintenance-remote.ts", "src/lib/dataset-maintenance-flow-identity-capture.ts", "src/lib/process-refresh-references.ts"];
|
|
130
|
+
readonly flowproperties: readonly ["src/lib/dataset-support-cache.ts", "src/lib/dataset-save-draft-run.ts", "src/lib/dataset-remote-verify.ts", "src/lib/dataset-maintenance-remote.ts", "src/lib/dataset-maintenance-flow-identity-capture.ts", "src/lib/process-refresh-references.ts"];
|
|
131
131
|
readonly flows: readonly ["src/lib/flow-read.ts", "src/lib/flow-list.ts", "src/lib/flow-publish-version.ts", "src/lib/dataset-save-draft-run.ts", "src/lib/dataset-remote-verify.ts", "src/lib/dataset-maintenance-remote.ts", "src/lib/dataset-maintenance-flow-identity-capture.ts", "src/lib/process-refresh-references.ts", "src/lib/dataset-maintenance-clear-account.ts"];
|
|
132
132
|
readonly ilcd: readonly [];
|
|
133
133
|
readonly lciamethods: readonly ["src/lib/dataset-remote-verify.ts", "src/lib/dataset-maintenance-remote.ts", "src/lib/process-refresh-references.ts"];
|
|
134
134
|
readonly lifecyclemodels: readonly ["src/lib/lifecyclemodel-bundle-save.ts", "src/lib/process-dedup-review.ts", "src/lib/dataset-remote-verify.ts", "src/lib/dataset-maintenance-remote.ts", "src/lib/supabase-json-ordered-write.ts", "src/lib/dataset-maintenance-clear-account.ts"];
|
|
135
135
|
readonly processes: readonly ["src/lib/process-get.ts", "src/lib/process-list.ts", "src/lib/process-save-draft.ts", "src/lib/process-scope-statistics.ts", "src/lib/process-dedup-review.ts", "src/lib/process-refresh-references.ts", "src/lib/dataset-save-draft-run.ts", "src/lib/dataset-remote-verify.ts", "src/lib/dataset-maintenance-remote.ts", "src/lib/supabase-json-ordered-write.ts", "src/lib/supabase-rest.ts", "src/lib/dataset-maintenance-clear-account.ts"];
|
|
136
136
|
readonly sources: readonly ["src/lib/dataset-save-draft-run.ts", "src/lib/dataset-remote-verify.ts", "src/lib/dataset-maintenance-remote.ts", "src/lib/supabase-json-ordered-write.ts", "src/lib/process-refresh-references.ts", "src/lib/dataset-maintenance-clear-account.ts"];
|
|
137
|
-
readonly unitgroups: readonly ["src/lib/dataset-save-draft-run.ts", "src/lib/dataset-remote-verify.ts", "src/lib/dataset-maintenance-remote.ts", "src/lib/dataset-maintenance-flow-identity-capture.ts", "src/lib/process-refresh-references.ts"];
|
|
137
|
+
readonly unitgroups: readonly ["src/lib/dataset-support-cache.ts", "src/lib/dataset-save-draft-run.ts", "src/lib/dataset-remote-verify.ts", "src/lib/dataset-maintenance-remote.ts", "src/lib/dataset-maintenance-flow-identity-capture.ts", "src/lib/process-refresh-references.ts"];
|
|
138
138
|
};
|
|
139
139
|
readonly views: readonly [];
|
|
140
140
|
readonly rpcs: {
|
|
@@ -23,6 +23,7 @@ export const DATA_API_RELATION_CONSUMERS = {
|
|
|
23
23
|
'src/lib/dataset-maintenance-clear-account.ts',
|
|
24
24
|
],
|
|
25
25
|
flowproperties: [
|
|
26
|
+
'src/lib/dataset-support-cache.ts',
|
|
26
27
|
'src/lib/dataset-save-draft-run.ts',
|
|
27
28
|
'src/lib/dataset-remote-verify.ts',
|
|
28
29
|
'src/lib/dataset-maintenance-remote.ts',
|
|
@@ -77,6 +78,7 @@ export const DATA_API_RELATION_CONSUMERS = {
|
|
|
77
78
|
'src/lib/dataset-maintenance-clear-account.ts',
|
|
78
79
|
],
|
|
79
80
|
unitgroups: [
|
|
81
|
+
'src/lib/dataset-support-cache.ts',
|
|
80
82
|
'src/lib/dataset-save-draft-run.ts',
|
|
81
83
|
'src/lib/dataset-remote-verify.ts',
|
|
82
84
|
'src/lib/dataset-maintenance-remote.ts',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"supabase-data-api-contract.js","sourceRoot":"","sources":["../../../src/lib/supabase-data-api-contract.ts"],"names":[],"mappings":"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","sourcesContent":["import { CliError } from './errors.js';\nimport { DATA_API_RPC_REPLAY_CLASSIFICATION } from './supabase-data-api-replay.js';\nexport {\n DATA_API_RPC_REPLAY_CLASSIFICATION,\n isDataApiAuthRefreshReplaySafe,\n} from './supabase-data-api-replay.js';\n\nexport const DATA_API_PROFILE_ENV = 'TIANGONG_LCA_DATA_API_PROFILE';\nexport const DATA_API_PROFILES = ['api-contract-v1'] as const;\nexport type DataApiProfile = (typeof DATA_API_PROFILES)[number];\nexport type DataApiRole = 'anon' | 'authenticated' | 'service_role';\n\nexport const CORE_PUBLIC_RELATIONS = [\n 'contacts',\n 'flowproperties',\n 'flows',\n 'ilcd',\n 'lciamethods',\n 'lifecyclemodels',\n 'processes',\n 'sources',\n 'unitgroups',\n] as const;\nexport type CorePublicRelation = (typeof CORE_PUBLIC_RELATIONS)[number];\n\nexport const DATA_API_RELATION_CONSUMERS = {\n contacts: [\n 'src/lib/dataset-save-draft-run.ts',\n 'src/lib/dataset-remote-verify.ts',\n 'src/lib/dataset-maintenance-remote.ts',\n 'src/lib/process-refresh-references.ts',\n 'src/lib/dataset-maintenance-clear-account.ts',\n ],\n flowproperties: [\n 'src/lib/dataset-save-draft-run.ts',\n 'src/lib/dataset-remote-verify.ts',\n 'src/lib/dataset-maintenance-remote.ts',\n 'src/lib/dataset-maintenance-flow-identity-capture.ts',\n 'src/lib/process-refresh-references.ts',\n ],\n flows: [\n 'src/lib/flow-read.ts',\n 'src/lib/flow-list.ts',\n 'src/lib/flow-publish-version.ts',\n 'src/lib/dataset-save-draft-run.ts',\n 'src/lib/dataset-remote-verify.ts',\n 'src/lib/dataset-maintenance-remote.ts',\n 'src/lib/dataset-maintenance-flow-identity-capture.ts',\n 'src/lib/process-refresh-references.ts',\n 'src/lib/dataset-maintenance-clear-account.ts',\n ],\n ilcd: [],\n lciamethods: [\n 'src/lib/dataset-remote-verify.ts',\n 'src/lib/dataset-maintenance-remote.ts',\n 'src/lib/process-refresh-references.ts',\n ],\n lifecyclemodels: [\n 'src/lib/lifecyclemodel-bundle-save.ts',\n 'src/lib/process-dedup-review.ts',\n 'src/lib/dataset-remote-verify.ts',\n 'src/lib/dataset-maintenance-remote.ts',\n 'src/lib/supabase-json-ordered-write.ts',\n 'src/lib/dataset-maintenance-clear-account.ts',\n ],\n processes: [\n 'src/lib/process-get.ts',\n 'src/lib/process-list.ts',\n 'src/lib/process-save-draft.ts',\n 'src/lib/process-scope-statistics.ts',\n 'src/lib/process-dedup-review.ts',\n 'src/lib/process-refresh-references.ts',\n 'src/lib/dataset-save-draft-run.ts',\n 'src/lib/dataset-remote-verify.ts',\n 'src/lib/dataset-maintenance-remote.ts',\n 'src/lib/supabase-json-ordered-write.ts',\n 'src/lib/supabase-rest.ts',\n 'src/lib/dataset-maintenance-clear-account.ts',\n ],\n sources: [\n 'src/lib/dataset-save-draft-run.ts',\n 'src/lib/dataset-remote-verify.ts',\n 'src/lib/dataset-maintenance-remote.ts',\n 'src/lib/supabase-json-ordered-write.ts',\n 'src/lib/process-refresh-references.ts',\n 'src/lib/dataset-maintenance-clear-account.ts',\n ],\n unitgroups: [\n 'src/lib/dataset-save-draft-run.ts',\n 'src/lib/dataset-remote-verify.ts',\n 'src/lib/dataset-maintenance-remote.ts',\n 'src/lib/dataset-maintenance-flow-identity-capture.ts',\n 'src/lib/process-refresh-references.ts',\n ],\n} as const satisfies Record<CorePublicRelation, readonly string[]>;\n\ntype RpcTarget = {\n targetSchema: 'api';\n signature: string;\n};\n\nexport const DATA_API_RPC_TARGETS = {\n cmd_dataset_alias_execution_admit_guarded: {\n targetSchema: 'api',\n signature: 'api.cmd_dataset_alias_execution_admit_guarded(p_request jsonb)',\n },\n cmd_dataset_alias_execution_gate_guarded: {\n targetSchema: 'api',\n signature:\n 'api.cmd_dataset_alias_execution_gate_guarded(p_request_id uuid, p_preflight_token text, p_gate_name text)',\n },\n cmd_dataset_alias_execution_preflight_guarded: {\n targetSchema: 'api',\n signature: 'api.cmd_dataset_alias_execution_preflight_guarded(p_request jsonb)',\n },\n cmd_dataset_alias_execution_read: {\n targetSchema: 'api',\n signature: 'api.cmd_dataset_alias_execution_read(p_request_id uuid)',\n },\n cmd_dataset_delete: {\n targetSchema: 'api',\n signature: 'api.cmd_dataset_delete(p_table text, p_id uuid, p_version text, p_audit jsonb)',\n },\n cmd_dataset_derivative_rebuild_plan_guarded: {\n targetSchema: 'api',\n signature: 'api.cmd_dataset_derivative_rebuild_plan_guarded(p_plan jsonb)',\n },\n cmd_dataset_derivative_rebuild_read: {\n targetSchema: 'api',\n signature: 'api.cmd_dataset_derivative_rebuild_read(p_request_id uuid)',\n },\n cmd_dataset_derivative_rebuild_snapshot: {\n targetSchema: 'api',\n signature:\n 'api.cmd_dataset_derivative_rebuild_snapshot(p_table text, p_id uuid, p_version text)',\n },\n cmd_dataset_flow_identity_capture_attest_guarded: {\n targetSchema: 'api',\n signature: 'api.cmd_dataset_flow_identity_capture_attest_guarded(p_request jsonb)',\n },\n cmd_dataset_flow_identity_process_rewrite_guarded: {\n targetSchema: 'api',\n signature:\n 'api.cmd_dataset_flow_identity_process_rewrite_guarded(p_scope_id uuid, p_request jsonb, p_authorization jsonb)',\n },\n cmd_dataset_flow_identity_scope_finalize_guarded: {\n targetSchema: 'api',\n signature:\n 'api.cmd_dataset_flow_identity_scope_finalize_guarded(p_scope_id uuid, p_request jsonb, p_authorization jsonb)',\n },\n cmd_dataset_flow_identity_scope_lookup: {\n targetSchema: 'api',\n signature: 'api.cmd_dataset_flow_identity_scope_lookup(p_request jsonb)',\n },\n cmd_dataset_flow_identity_scope_preflight_guarded: {\n targetSchema: 'api',\n signature: 'api.cmd_dataset_flow_identity_scope_preflight_guarded(p_request jsonb)',\n },\n cmd_dataset_flow_identity_scope_read: {\n targetSchema: 'api',\n signature: 'api.cmd_dataset_flow_identity_scope_read(p_scope_id uuid)',\n },\n cmd_dataset_flow_identity_scope_recover_guarded: {\n targetSchema: 'api',\n signature:\n 'api.cmd_dataset_flow_identity_scope_recover_guarded(p_scope_id uuid, p_request jsonb)',\n },\n cmd_dataset_save_draft: {\n targetSchema: 'api',\n signature:\n 'api.cmd_dataset_save_draft(p_table text, p_id uuid, p_version text, p_json_ordered jsonb, p_model_id uuid, p_rule_verification boolean, p_audit jsonb, p_model_version text)',\n },\n} as const satisfies Record<string, RpcTarget>;\n\nexport type DataApiRpc = keyof typeof DATA_API_RPC_TARGETS;\n\nexport const DATA_API_CONTRACT = {\n schemaVersion: 'tiangong-lca-cli.data-api-contract.v1',\n databaseContract: {\n repository: 'tiangong-lca/database-engine',\n databaseCommit: '1320dcc506fe37af6b625ae30fbe0bec38cf87c6',\n migrationHead: '20260902104500',\n migrationSetGitTreeSha: '88e212220c0037cee673d0522340d3cca5e791dd',\n contractMigrations: {\n fullSchemaCutover: {\n path: 'supabase/migrations/20260805130000_full_schema_cutover.sql',\n sha256: 'd409022fb25d9313d17b0f76216ca6e4abbfce7d6c5b6e74c869314d1c7e5afb',\n },\n apiContractClosure: {\n path: 'supabase/migrations/20260806160000_api_contract_closure.sql',\n sha256: 'e0e7aec8e03d70c60ee0d5c2b332ce73fa7b4b229725c9a9fcb0e1a1d7e8c511',\n },\n processModelVersionContract: {\n path: 'supabase/migrations/20260902100000_process_model_version_contract.sql',\n sha256: '99cbaf474098281ea8c57fcef093174d0ef78a18300f133dd8cc6f9e59a4a29b',\n },\n processSaveDraftModelVersion: {\n path: 'supabase/migrations/20260902103509_add_process_model_version_to_dataset_save_draft.sql',\n sha256: 'ca93f3279673e292803bd8c477aec76b772c7246e16114808d31e64994037723',\n },\n migrationHead: {\n path: 'supabase/migrations/20260902104500_use_exact_model_version_in_review_ownership.sql',\n sha256: '538ec3001f7683b57817e4a89973ded127522ce94521720ed583de99711bbe60',\n },\n },\n contractReady: true,\n snapshotRole: 'frozen-process-model-version-contract',\n provenanceIssue: 'tiangong-lca/database-engine#589',\n publicCoreTableCount: 9,\n publicRoutineCount: 0,\n },\n profiles: {\n 'api-contract-v1': {\n phase: 'contract',\n description: 'Frozen api RPC profile for database-engine migration head 20260902104500.',\n },\n },\n corePublicRelations: CORE_PUBLIC_RELATIONS,\n relationConsumers: DATA_API_RELATION_CONSUMERS,\n views: [],\n rpcs: DATA_API_RPC_TARGETS,\n rpcReplayClassification: DATA_API_RPC_REPLAY_CLASSIFICATION,\n cliRolePolicy: {\n anon: 'deny',\n authenticated: 'allow',\n service_role: 'deny',\n },\n retryPolicy: {\n reads:\n 'GET/HEAD and manifest-classified read RPCs permit one auth-refresh replay only after 401/403',\n mutations:\n 'no automatic transport retry; recovery must use the capability idempotency/read path',\n },\n retiredCapabilities: [\n {\n capability: 'rpc:cmd_dataset_alias_plan_guarded',\n targetSchema: 'private',\n reason:\n 'The whole-plan executor is private. Authenticated CLI execution uses the frozen alias execution preflight/gate/admit/read api capabilities.',\n },\n ],\n blockers: [],\n} as const;\n\nexport type ResolvedDataApiCapability = {\n kind: 'relation' | 'rpc';\n name: string;\n schema: 'public' | 'api';\n profile: DataApiProfile;\n role: DataApiRole;\n signature: string | null;\n};\n\nfunction isCorePublicRelation(value: string): value is CorePublicRelation {\n return (CORE_PUBLIC_RELATIONS as readonly string[]).includes(value);\n}\n\nfunction isDataApiRpc(value: string): value is DataApiRpc {\n return Object.hasOwn(DATA_API_RPC_TARGETS, value);\n}\n\nexport function resolveDataApiProfile(env: NodeJS.ProcessEnv = process.env): DataApiProfile {\n const value = env[DATA_API_PROFILE_ENV]?.trim() || 'api-contract-v1';\n if ((DATA_API_PROFILES as readonly string[]).includes(value)) {\n return value as DataApiProfile;\n }\n throw new CliError(`Unsupported ${DATA_API_PROFILE_ENV}: ${value}`, {\n code: 'DATA_API_PROFILE_INVALID',\n exitCode: 2,\n details: { supported: DATA_API_PROFILES },\n });\n}\n\nfunction assertCliRole(role: DataApiRole): void {\n if (role !== 'authenticated') {\n throw new CliError(`The CLI Data API adapter does not accept the ${role} role.`, {\n code: 'DATA_API_ROLE_FORBIDDEN',\n exitCode: 2,\n details: { role, allowed_roles: ['authenticated'] },\n });\n }\n}\n\nexport function resolveDataApiCapability(options: {\n kind: 'relation' | 'rpc';\n name: string;\n env?: NodeJS.ProcessEnv;\n profile?: DataApiProfile;\n role?: DataApiRole;\n}): ResolvedDataApiCapability {\n const profile = options.profile ?? resolveDataApiProfile(options.env);\n const role = options.role ?? 'authenticated';\n assertCliRole(role);\n\n if (options.kind === 'relation') {\n if (!isCorePublicRelation(options.name)) {\n throw new CliError(`Unmanifested Data API relation: ${options.name}`, {\n code: 'DATA_API_CAPABILITY_UNMANIFESTED',\n exitCode: 2,\n details: { kind: options.kind, name: options.name },\n });\n }\n return {\n kind: 'relation',\n name: options.name,\n schema: 'public',\n profile,\n role,\n signature: null,\n };\n }\n\n if (!isDataApiRpc(options.name)) {\n throw new CliError(`Unmanifested Data API RPC: ${options.name}`, {\n code: 'DATA_API_CAPABILITY_UNMANIFESTED',\n exitCode: 2,\n details: { kind: options.kind, name: options.name },\n });\n }\n const target = DATA_API_RPC_TARGETS[options.name];\n return {\n kind: 'rpc',\n name: options.name,\n schema: 'api',\n profile,\n role,\n signature: target.signature,\n };\n}\n\nexport function applyDataApiProfileHeaders(\n headers: HeadersInit | undefined,\n capability: ResolvedDataApiCapability,\n method = 'GET',\n): Record<string, string> {\n const resolved = new Headers(headers);\n const normalizedMethod = method.toUpperCase();\n if (normalizedMethod === 'GET' || normalizedMethod === 'HEAD') {\n resolved.set('Accept-Profile', capability.schema);\n } else {\n resolved.set('Content-Profile', capability.schema);\n }\n return Object.fromEntries(resolved.entries());\n}\n\nexport function resolveDataApiCapabilityFromUrl(options: {\n url: string;\n method?: string;\n env?: NodeJS.ProcessEnv;\n profile?: DataApiProfile;\n}): ResolvedDataApiCapability {\n const parsed = new URL(options.url);\n const marker = '/rest/v1/';\n const markerIndex = parsed.pathname.indexOf(marker);\n if (markerIndex < 0) {\n throw new CliError(`URL is not a Supabase Data API route: ${options.url}`, {\n code: 'DATA_API_URL_INVALID',\n exitCode: 2,\n });\n }\n const segments = parsed.pathname\n .slice(markerIndex + marker.length)\n .split('/')\n .filter(Boolean);\n if (segments[0] === 'rpc' && segments[1]) {\n return resolveDataApiCapability({\n kind: 'rpc',\n name: segments[1],\n env: options.env,\n profile: options.profile,\n });\n }\n if (segments[0]) {\n return resolveDataApiCapability({\n kind: 'relation',\n name: segments[0],\n env: options.env,\n profile: options.profile,\n });\n }\n throw new CliError(`Data API URL has no relation or RPC name: ${options.url}`, {\n code: 'DATA_API_URL_INVALID',\n exitCode: 2,\n });\n}\n\nexport function isDataApiUrl(url: string): boolean {\n return new URL(url).pathname.includes('/rest/v1/');\n}\n\nexport function buildDataApiUrl(\n restBaseUrl: string,\n capability: Pick<ResolvedDataApiCapability, 'kind' | 'name'>,\n): string {\n const base = restBaseUrl.replace(/\\/+$/u, '');\n return capability.kind === 'rpc'\n ? `${base}/rpc/${capability.name}`\n : `${base}/${capability.name}`;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"supabase-data-api-contract.js","sourceRoot":"","sources":["../../../src/lib/supabase-data-api-contract.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,kCAAkC,EAAE,MAAM,+BAA+B,CAAC;AACnF,OAAO,EACL,kCAAkC,EAClC,8BAA8B,GAC/B,MAAM,+BAA+B,CAAC;AAEvC,MAAM,CAAC,MAAM,oBAAoB,GAAG,+BAA+B,CAAC;AACpE,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,iBAAiB,CAAU,CAAC;AAI9D,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,UAAU;IACV,gBAAgB;IAChB,OAAO;IACP,MAAM;IACN,aAAa;IACb,iBAAiB;IACjB,WAAW;IACX,SAAS;IACT,YAAY;CACJ,CAAC;AAGX,MAAM,CAAC,MAAM,2BAA2B,GAAG;IACzC,QAAQ,EAAE;QACR,mCAAmC;QACnC,kCAAkC;QAClC,uCAAuC;QACvC,uCAAuC;QACvC,8CAA8C;KAC/C;IACD,cAAc,EAAE;QACd,kCAAkC;QAClC,mCAAmC;QACnC,kCAAkC;QAClC,uCAAuC;QACvC,sDAAsD;QACtD,uCAAuC;KACxC;IACD,KAAK,EAAE;QACL,sBAAsB;QACtB,sBAAsB;QACtB,iCAAiC;QACjC,mCAAmC;QACnC,kCAAkC;QAClC,uCAAuC;QACvC,sDAAsD;QACtD,uCAAuC;QACvC,8CAA8C;KAC/C;IACD,IAAI,EAAE,EAAE;IACR,WAAW,EAAE;QACX,kCAAkC;QAClC,uCAAuC;QACvC,uCAAuC;KACxC;IACD,eAAe,EAAE;QACf,uCAAuC;QACvC,iCAAiC;QACjC,kCAAkC;QAClC,uCAAuC;QACvC,wCAAwC;QACxC,8CAA8C;KAC/C;IACD,SAAS,EAAE;QACT,wBAAwB;QACxB,yBAAyB;QACzB,+BAA+B;QAC/B,qCAAqC;QACrC,iCAAiC;QACjC,uCAAuC;QACvC,mCAAmC;QACnC,kCAAkC;QAClC,uCAAuC;QACvC,wCAAwC;QACxC,0BAA0B;QAC1B,8CAA8C;KAC/C;IACD,OAAO,EAAE;QACP,mCAAmC;QACnC,kCAAkC;QAClC,uCAAuC;QACvC,wCAAwC;QACxC,uCAAuC;QACvC,8CAA8C;KAC/C;IACD,UAAU,EAAE;QACV,kCAAkC;QAClC,mCAAmC;QACnC,kCAAkC;QAClC,uCAAuC;QACvC,sDAAsD;QACtD,uCAAuC;KACxC;CAC+D,CAAC;AAOnE,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,yCAAyC,EAAE;QACzC,YAAY,EAAE,KAAK;QACnB,SAAS,EAAE,gEAAgE;KAC5E;IACD,wCAAwC,EAAE;QACxC,YAAY,EAAE,KAAK;QACnB,SAAS,EACP,2GAA2G;KAC9G;IACD,6CAA6C,EAAE;QAC7C,YAAY,EAAE,KAAK;QACnB,SAAS,EAAE,oEAAoE;KAChF;IACD,gCAAgC,EAAE;QAChC,YAAY,EAAE,KAAK;QACnB,SAAS,EAAE,yDAAyD;KACrE;IACD,kBAAkB,EAAE;QAClB,YAAY,EAAE,KAAK;QACnB,SAAS,EAAE,gFAAgF;KAC5F;IACD,2CAA2C,EAAE;QAC3C,YAAY,EAAE,KAAK;QACnB,SAAS,EAAE,+DAA+D;KAC3E;IACD,mCAAmC,EAAE;QACnC,YAAY,EAAE,KAAK;QACnB,SAAS,EAAE,4DAA4D;KACxE;IACD,uCAAuC,EAAE;QACvC,YAAY,EAAE,KAAK;QACnB,SAAS,EACP,sFAAsF;KACzF;IACD,gDAAgD,EAAE;QAChD,YAAY,EAAE,KAAK;QACnB,SAAS,EAAE,uEAAuE;KACnF;IACD,iDAAiD,EAAE;QACjD,YAAY,EAAE,KAAK;QACnB,SAAS,EACP,gHAAgH;KACnH;IACD,gDAAgD,EAAE;QAChD,YAAY,EAAE,KAAK;QACnB,SAAS,EACP,+GAA+G;KAClH;IACD,sCAAsC,EAAE;QACtC,YAAY,EAAE,KAAK;QACnB,SAAS,EAAE,6DAA6D;KACzE;IACD,iDAAiD,EAAE;QACjD,YAAY,EAAE,KAAK;QACnB,SAAS,EAAE,wEAAwE;KACpF;IACD,oCAAoC,EAAE;QACpC,YAAY,EAAE,KAAK;QACnB,SAAS,EAAE,2DAA2D;KACvE;IACD,+CAA+C,EAAE;QAC/C,YAAY,EAAE,KAAK;QACnB,SAAS,EACP,uFAAuF;KAC1F;IACD,sBAAsB,EAAE;QACtB,YAAY,EAAE,KAAK;QACnB,SAAS,EACP,8KAA8K;KACjL;CAC2C,CAAC;AAI/C,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,aAAa,EAAE,uCAAuC;IACtD,gBAAgB,EAAE;QAChB,UAAU,EAAE,8BAA8B;QAC1C,cAAc,EAAE,0CAA0C;QAC1D,aAAa,EAAE,gBAAgB;QAC/B,sBAAsB,EAAE,0CAA0C;QAClE,kBAAkB,EAAE;YAClB,iBAAiB,EAAE;gBACjB,IAAI,EAAE,4DAA4D;gBAClE,MAAM,EAAE,kEAAkE;aAC3E;YACD,kBAAkB,EAAE;gBAClB,IAAI,EAAE,6DAA6D;gBACnE,MAAM,EAAE,kEAAkE;aAC3E;YACD,2BAA2B,EAAE;gBAC3B,IAAI,EAAE,uEAAuE;gBAC7E,MAAM,EAAE,kEAAkE;aAC3E;YACD,4BAA4B,EAAE;gBAC5B,IAAI,EAAE,wFAAwF;gBAC9F,MAAM,EAAE,kEAAkE;aAC3E;YACD,aAAa,EAAE;gBACb,IAAI,EAAE,oFAAoF;gBAC1F,MAAM,EAAE,kEAAkE;aAC3E;SACF;QACD,aAAa,EAAE,IAAI;QACnB,YAAY,EAAE,uCAAuC;QACrD,eAAe,EAAE,kCAAkC;QACnD,oBAAoB,EAAE,CAAC;QACvB,kBAAkB,EAAE,CAAC;KACtB;IACD,QAAQ,EAAE;QACR,iBAAiB,EAAE;YACjB,KAAK,EAAE,UAAU;YACjB,WAAW,EAAE,2EAA2E;SACzF;KACF;IACD,mBAAmB,EAAE,qBAAqB;IAC1C,iBAAiB,EAAE,2BAA2B;IAC9C,KAAK,EAAE,EAAE;IACT,IAAI,EAAE,oBAAoB;IAC1B,uBAAuB,EAAE,kCAAkC;IAC3D,aAAa,EAAE;QACb,IAAI,EAAE,MAAM;QACZ,aAAa,EAAE,OAAO;QACtB,YAAY,EAAE,MAAM;KACrB;IACD,WAAW,EAAE;QACX,KAAK,EACH,8FAA8F;QAChG,SAAS,EACP,sFAAsF;KACzF;IACD,mBAAmB,EAAE;QACnB;YACE,UAAU,EAAE,oCAAoC;YAChD,YAAY,EAAE,SAAS;YACvB,MAAM,EACJ,6IAA6I;SAChJ;KACF;IACD,QAAQ,EAAE,EAAE;CACJ,CAAC;AAWX,SAAS,oBAAoB,CAAC,KAAa;IACzC,OAAQ,qBAA2C,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACtE,CAAC;AAED,SAAS,YAAY,CAAC,KAAa;IACjC,OAAO,MAAM,CAAC,MAAM,CAAC,oBAAoB,EAAE,KAAK,CAAC,CAAC;AACpD,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,GAAG,GAAsB,OAAO,CAAC,GAAG;IACxE,MAAM,KAAK,GAAG,GAAG,CAAC,oBAAoB,CAAC,EAAE,IAAI,EAAE,IAAI,iBAAiB,CAAC;IACrE,IAAK,iBAAuC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC7D,OAAO,KAAuB,CAAC;IACjC,CAAC;IACD,MAAM,IAAI,QAAQ,CAAC,eAAe,oBAAoB,KAAK,KAAK,EAAE,EAAE;QAClE,IAAI,EAAE,0BAA0B;QAChC,QAAQ,EAAE,CAAC;QACX,OAAO,EAAE,EAAE,SAAS,EAAE,iBAAiB,EAAE;KAC1C,CAAC,CAAC;AACL,CAAC;AAED,SAAS,aAAa,CAAC,IAAiB;IACtC,IAAI,IAAI,KAAK,eAAe,EAAE,CAAC;QAC7B,MAAM,IAAI,QAAQ,CAAC,gDAAgD,IAAI,QAAQ,EAAE;YAC/E,IAAI,EAAE,yBAAyB;YAC/B,QAAQ,EAAE,CAAC;YACX,OAAO,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC,eAAe,CAAC,EAAE;SACpD,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,OAMxC;IACC,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,qBAAqB,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACtE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,eAAe,CAAC;IAC7C,aAAa,CAAC,IAAI,CAAC,CAAC;IAEpB,IAAI,OAAO,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;QAChC,IAAI,CAAC,oBAAoB,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YACxC,MAAM,IAAI,QAAQ,CAAC,mCAAmC,OAAO,CAAC,IAAI,EAAE,EAAE;gBACpE,IAAI,EAAE,kCAAkC;gBACxC,QAAQ,EAAE,CAAC;gBACX,OAAO,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE;aACpD,CAAC,CAAC;QACL,CAAC;QACD,OAAO;YACL,IAAI,EAAE,UAAU;YAChB,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,MAAM,EAAE,QAAQ;YAChB,OAAO;YACP,IAAI;YACJ,SAAS,EAAE,IAAI;SAChB,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QAChC,MAAM,IAAI,QAAQ,CAAC,8BAA8B,OAAO,CAAC,IAAI,EAAE,EAAE;YAC/D,IAAI,EAAE,kCAAkC;YACxC,QAAQ,EAAE,CAAC;YACX,OAAO,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE;SACpD,CAAC,CAAC;IACL,CAAC;IACD,MAAM,MAAM,GAAG,oBAAoB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAClD,OAAO;QACL,IAAI,EAAE,KAAK;QACX,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,MAAM,EAAE,KAAK;QACb,OAAO;QACP,IAAI;QACJ,SAAS,EAAE,MAAM,CAAC,SAAS;KAC5B,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,0BAA0B,CACxC,OAAgC,EAChC,UAAqC,EACrC,MAAM,GAAG,KAAK;IAEd,MAAM,QAAQ,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IACtC,MAAM,gBAAgB,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;IAC9C,IAAI,gBAAgB,KAAK,KAAK,IAAI,gBAAgB,KAAK,MAAM,EAAE,CAAC;QAC9D,QAAQ,CAAC,GAAG,CAAC,gBAAgB,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;IACpD,CAAC;SAAM,CAAC;QACN,QAAQ,CAAC,GAAG,CAAC,iBAAiB,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;IACrD,CAAC;IACD,OAAO,MAAM,CAAC,WAAW,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,+BAA+B,CAAC,OAK/C;IACC,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACpC,MAAM,MAAM,GAAG,WAAW,CAAC;IAC3B,MAAM,WAAW,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACpD,IAAI,WAAW,GAAG,CAAC,EAAE,CAAC;QACpB,MAAM,IAAI,QAAQ,CAAC,yCAAyC,OAAO,CAAC,GAAG,EAAE,EAAE;YACzE,IAAI,EAAE,sBAAsB;YAC5B,QAAQ,EAAE,CAAC;SACZ,CAAC,CAAC;IACL,CAAC;IACD,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ;SAC7B,KAAK,CAAC,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC;SAClC,KAAK,CAAC,GAAG,CAAC;SACV,MAAM,CAAC,OAAO,CAAC,CAAC;IACnB,IAAI,QAAQ,CAAC,CAAC,CAAC,KAAK,KAAK,IAAI,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;QACzC,OAAO,wBAAwB,CAAC;YAC9B,IAAI,EAAE,KAAK;YACX,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC;YACjB,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,OAAO,EAAE,OAAO,CAAC,OAAO;SACzB,CAAC,CAAC;IACL,CAAC;IACD,IAAI,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;QAChB,OAAO,wBAAwB,CAAC;YAC9B,IAAI,EAAE,UAAU;YAChB,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC;YACjB,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,OAAO,EAAE,OAAO,CAAC,OAAO;SACzB,CAAC,CAAC;IACL,CAAC;IACD,MAAM,IAAI,QAAQ,CAAC,6CAA6C,OAAO,CAAC,GAAG,EAAE,EAAE;QAC7E,IAAI,EAAE,sBAAsB;QAC5B,QAAQ,EAAE,CAAC;KACZ,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,GAAW;IACtC,OAAO,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;AACrD,CAAC;AAED,MAAM,UAAU,eAAe,CAC7B,WAAmB,EACnB,UAA4D;IAE5D,MAAM,IAAI,GAAG,WAAW,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAC9C,OAAO,UAAU,CAAC,IAAI,KAAK,KAAK;QAC9B,CAAC,CAAC,GAAG,IAAI,QAAQ,UAAU,CAAC,IAAI,EAAE;QAClC,CAAC,CAAC,GAAG,IAAI,IAAI,UAAU,CAAC,IAAI,EAAE,CAAC;AACnC,CAAC","sourcesContent":["import { CliError } from './errors.js';\nimport { DATA_API_RPC_REPLAY_CLASSIFICATION } from './supabase-data-api-replay.js';\nexport {\n DATA_API_RPC_REPLAY_CLASSIFICATION,\n isDataApiAuthRefreshReplaySafe,\n} from './supabase-data-api-replay.js';\n\nexport const DATA_API_PROFILE_ENV = 'TIANGONG_LCA_DATA_API_PROFILE';\nexport const DATA_API_PROFILES = ['api-contract-v1'] as const;\nexport type DataApiProfile = (typeof DATA_API_PROFILES)[number];\nexport type DataApiRole = 'anon' | 'authenticated' | 'service_role';\n\nexport const CORE_PUBLIC_RELATIONS = [\n 'contacts',\n 'flowproperties',\n 'flows',\n 'ilcd',\n 'lciamethods',\n 'lifecyclemodels',\n 'processes',\n 'sources',\n 'unitgroups',\n] as const;\nexport type CorePublicRelation = (typeof CORE_PUBLIC_RELATIONS)[number];\n\nexport const DATA_API_RELATION_CONSUMERS = {\n contacts: [\n 'src/lib/dataset-save-draft-run.ts',\n 'src/lib/dataset-remote-verify.ts',\n 'src/lib/dataset-maintenance-remote.ts',\n 'src/lib/process-refresh-references.ts',\n 'src/lib/dataset-maintenance-clear-account.ts',\n ],\n flowproperties: [\n 'src/lib/dataset-support-cache.ts',\n 'src/lib/dataset-save-draft-run.ts',\n 'src/lib/dataset-remote-verify.ts',\n 'src/lib/dataset-maintenance-remote.ts',\n 'src/lib/dataset-maintenance-flow-identity-capture.ts',\n 'src/lib/process-refresh-references.ts',\n ],\n flows: [\n 'src/lib/flow-read.ts',\n 'src/lib/flow-list.ts',\n 'src/lib/flow-publish-version.ts',\n 'src/lib/dataset-save-draft-run.ts',\n 'src/lib/dataset-remote-verify.ts',\n 'src/lib/dataset-maintenance-remote.ts',\n 'src/lib/dataset-maintenance-flow-identity-capture.ts',\n 'src/lib/process-refresh-references.ts',\n 'src/lib/dataset-maintenance-clear-account.ts',\n ],\n ilcd: [],\n lciamethods: [\n 'src/lib/dataset-remote-verify.ts',\n 'src/lib/dataset-maintenance-remote.ts',\n 'src/lib/process-refresh-references.ts',\n ],\n lifecyclemodels: [\n 'src/lib/lifecyclemodel-bundle-save.ts',\n 'src/lib/process-dedup-review.ts',\n 'src/lib/dataset-remote-verify.ts',\n 'src/lib/dataset-maintenance-remote.ts',\n 'src/lib/supabase-json-ordered-write.ts',\n 'src/lib/dataset-maintenance-clear-account.ts',\n ],\n processes: [\n 'src/lib/process-get.ts',\n 'src/lib/process-list.ts',\n 'src/lib/process-save-draft.ts',\n 'src/lib/process-scope-statistics.ts',\n 'src/lib/process-dedup-review.ts',\n 'src/lib/process-refresh-references.ts',\n 'src/lib/dataset-save-draft-run.ts',\n 'src/lib/dataset-remote-verify.ts',\n 'src/lib/dataset-maintenance-remote.ts',\n 'src/lib/supabase-json-ordered-write.ts',\n 'src/lib/supabase-rest.ts',\n 'src/lib/dataset-maintenance-clear-account.ts',\n ],\n sources: [\n 'src/lib/dataset-save-draft-run.ts',\n 'src/lib/dataset-remote-verify.ts',\n 'src/lib/dataset-maintenance-remote.ts',\n 'src/lib/supabase-json-ordered-write.ts',\n 'src/lib/process-refresh-references.ts',\n 'src/lib/dataset-maintenance-clear-account.ts',\n ],\n unitgroups: [\n 'src/lib/dataset-support-cache.ts',\n 'src/lib/dataset-save-draft-run.ts',\n 'src/lib/dataset-remote-verify.ts',\n 'src/lib/dataset-maintenance-remote.ts',\n 'src/lib/dataset-maintenance-flow-identity-capture.ts',\n 'src/lib/process-refresh-references.ts',\n ],\n} as const satisfies Record<CorePublicRelation, readonly string[]>;\n\ntype RpcTarget = {\n targetSchema: 'api';\n signature: string;\n};\n\nexport const DATA_API_RPC_TARGETS = {\n cmd_dataset_alias_execution_admit_guarded: {\n targetSchema: 'api',\n signature: 'api.cmd_dataset_alias_execution_admit_guarded(p_request jsonb)',\n },\n cmd_dataset_alias_execution_gate_guarded: {\n targetSchema: 'api',\n signature:\n 'api.cmd_dataset_alias_execution_gate_guarded(p_request_id uuid, p_preflight_token text, p_gate_name text)',\n },\n cmd_dataset_alias_execution_preflight_guarded: {\n targetSchema: 'api',\n signature: 'api.cmd_dataset_alias_execution_preflight_guarded(p_request jsonb)',\n },\n cmd_dataset_alias_execution_read: {\n targetSchema: 'api',\n signature: 'api.cmd_dataset_alias_execution_read(p_request_id uuid)',\n },\n cmd_dataset_delete: {\n targetSchema: 'api',\n signature: 'api.cmd_dataset_delete(p_table text, p_id uuid, p_version text, p_audit jsonb)',\n },\n cmd_dataset_derivative_rebuild_plan_guarded: {\n targetSchema: 'api',\n signature: 'api.cmd_dataset_derivative_rebuild_plan_guarded(p_plan jsonb)',\n },\n cmd_dataset_derivative_rebuild_read: {\n targetSchema: 'api',\n signature: 'api.cmd_dataset_derivative_rebuild_read(p_request_id uuid)',\n },\n cmd_dataset_derivative_rebuild_snapshot: {\n targetSchema: 'api',\n signature:\n 'api.cmd_dataset_derivative_rebuild_snapshot(p_table text, p_id uuid, p_version text)',\n },\n cmd_dataset_flow_identity_capture_attest_guarded: {\n targetSchema: 'api',\n signature: 'api.cmd_dataset_flow_identity_capture_attest_guarded(p_request jsonb)',\n },\n cmd_dataset_flow_identity_process_rewrite_guarded: {\n targetSchema: 'api',\n signature:\n 'api.cmd_dataset_flow_identity_process_rewrite_guarded(p_scope_id uuid, p_request jsonb, p_authorization jsonb)',\n },\n cmd_dataset_flow_identity_scope_finalize_guarded: {\n targetSchema: 'api',\n signature:\n 'api.cmd_dataset_flow_identity_scope_finalize_guarded(p_scope_id uuid, p_request jsonb, p_authorization jsonb)',\n },\n cmd_dataset_flow_identity_scope_lookup: {\n targetSchema: 'api',\n signature: 'api.cmd_dataset_flow_identity_scope_lookup(p_request jsonb)',\n },\n cmd_dataset_flow_identity_scope_preflight_guarded: {\n targetSchema: 'api',\n signature: 'api.cmd_dataset_flow_identity_scope_preflight_guarded(p_request jsonb)',\n },\n cmd_dataset_flow_identity_scope_read: {\n targetSchema: 'api',\n signature: 'api.cmd_dataset_flow_identity_scope_read(p_scope_id uuid)',\n },\n cmd_dataset_flow_identity_scope_recover_guarded: {\n targetSchema: 'api',\n signature:\n 'api.cmd_dataset_flow_identity_scope_recover_guarded(p_scope_id uuid, p_request jsonb)',\n },\n cmd_dataset_save_draft: {\n targetSchema: 'api',\n signature:\n 'api.cmd_dataset_save_draft(p_table text, p_id uuid, p_version text, p_json_ordered jsonb, p_model_id uuid, p_rule_verification boolean, p_audit jsonb, p_model_version text)',\n },\n} as const satisfies Record<string, RpcTarget>;\n\nexport type DataApiRpc = keyof typeof DATA_API_RPC_TARGETS;\n\nexport const DATA_API_CONTRACT = {\n schemaVersion: 'tiangong-lca-cli.data-api-contract.v1',\n databaseContract: {\n repository: 'tiangong-lca/database-engine',\n databaseCommit: '1320dcc506fe37af6b625ae30fbe0bec38cf87c6',\n migrationHead: '20260902104500',\n migrationSetGitTreeSha: '88e212220c0037cee673d0522340d3cca5e791dd',\n contractMigrations: {\n fullSchemaCutover: {\n path: 'supabase/migrations/20260805130000_full_schema_cutover.sql',\n sha256: 'd409022fb25d9313d17b0f76216ca6e4abbfce7d6c5b6e74c869314d1c7e5afb',\n },\n apiContractClosure: {\n path: 'supabase/migrations/20260806160000_api_contract_closure.sql',\n sha256: 'e0e7aec8e03d70c60ee0d5c2b332ce73fa7b4b229725c9a9fcb0e1a1d7e8c511',\n },\n processModelVersionContract: {\n path: 'supabase/migrations/20260902100000_process_model_version_contract.sql',\n sha256: '99cbaf474098281ea8c57fcef093174d0ef78a18300f133dd8cc6f9e59a4a29b',\n },\n processSaveDraftModelVersion: {\n path: 'supabase/migrations/20260902103509_add_process_model_version_to_dataset_save_draft.sql',\n sha256: 'ca93f3279673e292803bd8c477aec76b772c7246e16114808d31e64994037723',\n },\n migrationHead: {\n path: 'supabase/migrations/20260902104500_use_exact_model_version_in_review_ownership.sql',\n sha256: '538ec3001f7683b57817e4a89973ded127522ce94521720ed583de99711bbe60',\n },\n },\n contractReady: true,\n snapshotRole: 'frozen-process-model-version-contract',\n provenanceIssue: 'tiangong-lca/database-engine#589',\n publicCoreTableCount: 9,\n publicRoutineCount: 0,\n },\n profiles: {\n 'api-contract-v1': {\n phase: 'contract',\n description: 'Frozen api RPC profile for database-engine migration head 20260902104500.',\n },\n },\n corePublicRelations: CORE_PUBLIC_RELATIONS,\n relationConsumers: DATA_API_RELATION_CONSUMERS,\n views: [],\n rpcs: DATA_API_RPC_TARGETS,\n rpcReplayClassification: DATA_API_RPC_REPLAY_CLASSIFICATION,\n cliRolePolicy: {\n anon: 'deny',\n authenticated: 'allow',\n service_role: 'deny',\n },\n retryPolicy: {\n reads:\n 'GET/HEAD and manifest-classified read RPCs permit one auth-refresh replay only after 401/403',\n mutations:\n 'no automatic transport retry; recovery must use the capability idempotency/read path',\n },\n retiredCapabilities: [\n {\n capability: 'rpc:cmd_dataset_alias_plan_guarded',\n targetSchema: 'private',\n reason:\n 'The whole-plan executor is private. Authenticated CLI execution uses the frozen alias execution preflight/gate/admit/read api capabilities.',\n },\n ],\n blockers: [],\n} as const;\n\nexport type ResolvedDataApiCapability = {\n kind: 'relation' | 'rpc';\n name: string;\n schema: 'public' | 'api';\n profile: DataApiProfile;\n role: DataApiRole;\n signature: string | null;\n};\n\nfunction isCorePublicRelation(value: string): value is CorePublicRelation {\n return (CORE_PUBLIC_RELATIONS as readonly string[]).includes(value);\n}\n\nfunction isDataApiRpc(value: string): value is DataApiRpc {\n return Object.hasOwn(DATA_API_RPC_TARGETS, value);\n}\n\nexport function resolveDataApiProfile(env: NodeJS.ProcessEnv = process.env): DataApiProfile {\n const value = env[DATA_API_PROFILE_ENV]?.trim() || 'api-contract-v1';\n if ((DATA_API_PROFILES as readonly string[]).includes(value)) {\n return value as DataApiProfile;\n }\n throw new CliError(`Unsupported ${DATA_API_PROFILE_ENV}: ${value}`, {\n code: 'DATA_API_PROFILE_INVALID',\n exitCode: 2,\n details: { supported: DATA_API_PROFILES },\n });\n}\n\nfunction assertCliRole(role: DataApiRole): void {\n if (role !== 'authenticated') {\n throw new CliError(`The CLI Data API adapter does not accept the ${role} role.`, {\n code: 'DATA_API_ROLE_FORBIDDEN',\n exitCode: 2,\n details: { role, allowed_roles: ['authenticated'] },\n });\n }\n}\n\nexport function resolveDataApiCapability(options: {\n kind: 'relation' | 'rpc';\n name: string;\n env?: NodeJS.ProcessEnv;\n profile?: DataApiProfile;\n role?: DataApiRole;\n}): ResolvedDataApiCapability {\n const profile = options.profile ?? resolveDataApiProfile(options.env);\n const role = options.role ?? 'authenticated';\n assertCliRole(role);\n\n if (options.kind === 'relation') {\n if (!isCorePublicRelation(options.name)) {\n throw new CliError(`Unmanifested Data API relation: ${options.name}`, {\n code: 'DATA_API_CAPABILITY_UNMANIFESTED',\n exitCode: 2,\n details: { kind: options.kind, name: options.name },\n });\n }\n return {\n kind: 'relation',\n name: options.name,\n schema: 'public',\n profile,\n role,\n signature: null,\n };\n }\n\n if (!isDataApiRpc(options.name)) {\n throw new CliError(`Unmanifested Data API RPC: ${options.name}`, {\n code: 'DATA_API_CAPABILITY_UNMANIFESTED',\n exitCode: 2,\n details: { kind: options.kind, name: options.name },\n });\n }\n const target = DATA_API_RPC_TARGETS[options.name];\n return {\n kind: 'rpc',\n name: options.name,\n schema: 'api',\n profile,\n role,\n signature: target.signature,\n };\n}\n\nexport function applyDataApiProfileHeaders(\n headers: HeadersInit | undefined,\n capability: ResolvedDataApiCapability,\n method = 'GET',\n): Record<string, string> {\n const resolved = new Headers(headers);\n const normalizedMethod = method.toUpperCase();\n if (normalizedMethod === 'GET' || normalizedMethod === 'HEAD') {\n resolved.set('Accept-Profile', capability.schema);\n } else {\n resolved.set('Content-Profile', capability.schema);\n }\n return Object.fromEntries(resolved.entries());\n}\n\nexport function resolveDataApiCapabilityFromUrl(options: {\n url: string;\n method?: string;\n env?: NodeJS.ProcessEnv;\n profile?: DataApiProfile;\n}): ResolvedDataApiCapability {\n const parsed = new URL(options.url);\n const marker = '/rest/v1/';\n const markerIndex = parsed.pathname.indexOf(marker);\n if (markerIndex < 0) {\n throw new CliError(`URL is not a Supabase Data API route: ${options.url}`, {\n code: 'DATA_API_URL_INVALID',\n exitCode: 2,\n });\n }\n const segments = parsed.pathname\n .slice(markerIndex + marker.length)\n .split('/')\n .filter(Boolean);\n if (segments[0] === 'rpc' && segments[1]) {\n return resolveDataApiCapability({\n kind: 'rpc',\n name: segments[1],\n env: options.env,\n profile: options.profile,\n });\n }\n if (segments[0]) {\n return resolveDataApiCapability({\n kind: 'relation',\n name: segments[0],\n env: options.env,\n profile: options.profile,\n });\n }\n throw new CliError(`Data API URL has no relation or RPC name: ${options.url}`, {\n code: 'DATA_API_URL_INVALID',\n exitCode: 2,\n });\n}\n\nexport function isDataApiUrl(url: string): boolean {\n return new URL(url).pathname.includes('/rest/v1/');\n}\n\nexport function buildDataApiUrl(\n restBaseUrl: string,\n capability: Pick<ResolvedDataApiCapability, 'kind' | 'name'>,\n): string {\n const base = restBaseUrl.replace(/\\/+$/u, '');\n return capability.kind === 'rpc'\n ? `${base}/rpc/${capability.name}`\n : `${base}/${capability.name}`;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tiangong-lca/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.9",
|
|
4
4
|
"description": "Unified TianGong LCA CLI with direct REST adapters and low-entropy command surface.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -63,6 +63,7 @@
|
|
|
63
63
|
"lint-staged": "^17.4.1",
|
|
64
64
|
"oxlint": "^1.80.0",
|
|
65
65
|
"oxlint-tsgolint": "^7.0.2001",
|
|
66
|
+
"playwright": "1.62.1",
|
|
66
67
|
"prettier": "3.9.6",
|
|
67
68
|
"sigstore": "5.0.0",
|
|
68
69
|
"tsx": "^4.23.13",
|
|
@@ -95,6 +96,7 @@
|
|
|
95
96
|
"release:check-tag": "node ./scripts/ci/check-release-tag.cjs cli",
|
|
96
97
|
"release:assert-unpublished": "node ./scripts/ci/release-version.cjs assert-unpublished",
|
|
97
98
|
"release:verify-published": "node ./scripts/ci/verify-published-release.cjs",
|
|
98
|
-
"clean": "node --eval \"import('node:fs').then(({ rmSync }) => rmSync('dist', { recursive: true, force: true }))\""
|
|
99
|
+
"clean": "node --eval \"import('node:fs').then(({ rmSync }) => rmSync('dist', { recursive: true, force: true }))\"",
|
|
100
|
+
"live:oauth": "node --import tsx ./scripts/live/oauth-case.ts"
|
|
99
101
|
}
|
|
100
102
|
}
|