@tiangong-lca/cli 0.0.24 → 0.0.25
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 +37 -5
- package/dist/src/cli.js +194 -4
- package/dist/src/cli.js.map +1 -1
- package/dist/src/lib/dataset-maintenance-alias-request.js +99 -0
- package/dist/src/lib/dataset-maintenance-alias-request.js.map +1 -0
- package/dist/src/lib/dataset-maintenance-apply.js +12 -367
- package/dist/src/lib/dataset-maintenance-apply.js.map +1 -1
- package/dist/src/lib/dataset-maintenance-protected-contract.js +918 -0
- package/dist/src/lib/dataset-maintenance-protected-contract.js.map +1 -0
- package/dist/src/lib/dataset-maintenance-protected-run.js +771 -0
- package/dist/src/lib/dataset-maintenance-protected-run.js.map +1 -0
- package/dist/src/lib/dataset-maintenance-protected-verify.js +435 -0
- package/dist/src/lib/dataset-maintenance-protected-verify.js.map +1 -0
- package/dist/src/lib/dataset-maintenance-remote.js +116 -2
- package/dist/src/lib/dataset-maintenance-remote.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -17,8 +17,8 @@ checkPaths:
|
|
|
17
17
|
- bin/**
|
|
18
18
|
- src/cli.ts
|
|
19
19
|
- src/main.ts
|
|
20
|
-
lastReviewedAt: 2026-07-
|
|
21
|
-
lastReviewedCommit:
|
|
20
|
+
lastReviewedAt: 2026-07-15
|
|
21
|
+
lastReviewedCommit: ca0cdd7549cad9003d08fb338223ba74682955ae
|
|
22
22
|
---
|
|
23
23
|
|
|
24
24
|
# TianGong LCA CLI
|
|
@@ -31,6 +31,8 @@ Review note, 2026-07-13: maintenance scans now prove exact-count pagination even
|
|
|
31
31
|
|
|
32
32
|
Review note, 2026-07-14: maintenance now includes the protected derivative-only `rebuild-derivatives` operation. V1 plans exactly one current-owner state-0 process with `action=rebuild_derivatives`, `target_mode=owner_draft`, and components `extracted_md` plus `embedding_ft`. Apply only proves guarded-RPC admission (`accepted`/`queued`); independent verify reports `pending`, `passed`, or `failed`.
|
|
33
33
|
|
|
34
|
+
Review note, 2026-07-15: `dataset maintenance run-protected` adds a production-only path for one sealed private alias execution and its exact 50-target derivative closure. The protected executor is server-dispatched and fenced by the authenticated owner plus exact actor/user_id/state_code=0 and plan-closure checks; RLS remains a defense on public and independent-read surfaces. It performs one server preflight, writes an immutable local attempt marker before one admission POST, and requires status-only recovery after any marker or ambiguous response. It has no dev, legacy-alias, publication, or state-code fallback.
|
|
35
|
+
|
|
34
36
|
## Run
|
|
35
37
|
|
|
36
38
|
One-off published run:
|
|
@@ -283,6 +285,7 @@ tiangong-lca dataset maintenance plan --scope ./maintenance-scope.json --operati
|
|
|
283
285
|
tiangong-lca dataset maintenance plan --scope ./derivative-rebuild-scope.json --operation rebuild-derivatives --out-dir /abs/path/to/derivative-rebuild --json
|
|
284
286
|
tiangong-lca dataset maintenance apply --plan /abs/path/to/dataset-maintenance/maintenance-plan.json --commit --approve-plan <sha256> --confirm <current-account-email> --timeout-ms 10000 --json
|
|
285
287
|
tiangong-lca dataset maintenance verify --plan /abs/path/to/dataset-maintenance/maintenance-plan.json --out-dir /abs/path/to/dataset-maintenance/verify --page-size 1000 --timeout-ms 10000 --json
|
|
288
|
+
tiangong-lca dataset maintenance run-protected --plan /abs/path/to/maintenance-plan.json --freeze /abs/path/to/protected-execution-seal.json --approval /abs/path/to/protected-approval.json --out-dir /abs/path/to/protected-run --status-only --json
|
|
286
289
|
tiangong-lca lifecyclemodel auto-build --input ./examples/lifecyclemodel-auto-build.request.json --out-dir /abs/path/to/lifecyclemodel-run --json
|
|
287
290
|
tiangong-lca lifecyclemodel validate-build --run-dir /abs/path/to/lifecyclemodel-run --json
|
|
288
291
|
tiangong-lca lifecyclemodel publish-build --run-dir /abs/path/to/lifecyclemodel-run --json
|
|
@@ -327,12 +330,12 @@ For `dataset references rewrite`, `--commit` executes the state-aware save-draft
|
|
|
327
330
|
|
|
328
331
|
## Dataset Maintenance
|
|
329
332
|
|
|
330
|
-
`dataset maintenance plan/apply/verify` is the row-level cleanup surface for bad imports, the fixed BAFU private alias rewrite, and
|
|
333
|
+
`dataset maintenance plan/apply/run-protected/verify` is the row-level cleanup surface for bad imports, the fixed BAFU private alias rewrite, and protected derivative rebuilds. Ordinary planning, apply, and independent verification use the authenticated account and RLS. The protected executor is server-dispatched and additionally enforces the sealed actor, user_id, state_code=0, exact target set, and closure hashes on every write.
|
|
331
334
|
|
|
332
335
|
```bash
|
|
333
336
|
tiangong-lca dataset maintenance plan \
|
|
334
337
|
--scope ./maintenance-scope.json \
|
|
335
|
-
--operation
|
|
338
|
+
--operation repair-references \
|
|
336
339
|
--out-dir ./dataset-maintenance \
|
|
337
340
|
--page-size 1000 \
|
|
338
341
|
--timeout-ms 10000 \
|
|
@@ -352,8 +355,37 @@ tiangong-lca dataset maintenance verify \
|
|
|
352
355
|
--page-size 1000 \
|
|
353
356
|
--timeout-ms 10000 \
|
|
354
357
|
--json
|
|
358
|
+
|
|
359
|
+
tiangong-lca dataset maintenance run-protected \
|
|
360
|
+
--plan ./protected-step2/maintenance-plan.json \
|
|
361
|
+
--freeze ./protected-step2/protected-execution-seal.json \
|
|
362
|
+
--approval ./protected-step2/protected-approval.json \
|
|
363
|
+
--out-dir ./protected-step2/run \
|
|
364
|
+
--commit \
|
|
365
|
+
--approve-execution <approved-execution-sha256> \
|
|
366
|
+
--confirm <current-account-email> \
|
|
367
|
+
--wait-seconds 60 \
|
|
368
|
+
--poll-ms 10000 \
|
|
369
|
+
--page-size 1000 \
|
|
370
|
+
--timeout-ms 10000 \
|
|
371
|
+
--json
|
|
372
|
+
|
|
373
|
+
tiangong-lca dataset maintenance run-protected \
|
|
374
|
+
--plan ./protected-step2/maintenance-plan.json \
|
|
375
|
+
--freeze ./protected-step2/protected-execution-seal.json \
|
|
376
|
+
--approval ./protected-step2/protected-approval.json \
|
|
377
|
+
--out-dir ./protected-step2/run \
|
|
378
|
+
--status-only \
|
|
379
|
+
--wait-seconds 60 \
|
|
380
|
+
--json
|
|
355
381
|
```
|
|
356
382
|
|
|
383
|
+
`run-protected` is a separate one-shot path for an already reviewed and sealed production execution; it does not replace ordinary planning. Both modes require the exact plan, freeze/seal, approval artifact, and private output directory. Commit mode additionally requires `--commit`, the exact approved execution identity through `--approve-execution`, and the authenticated account email through `--confirm`. `--status-only` is mutually exclusive with `--commit` and performs no preflight or admission.
|
|
384
|
+
|
|
385
|
+
Before requesting preflight, the command validates the sealed production project, full current-user RLS before-state, support closure, and exact derivative baseline. The server then returns the three expected gate digests and a token valid for at most 180 seconds; the CLI captures and compares the live gate receipts before admission. The server-dispatched write remains fenced to the authenticated actor's exact `user_id`, `state_code=0` rows and sealed plan/closure; independent readback still uses RLS. The CLI writes an immutable local submission marker and sends at most one admission POST. A marker, admission timeout, connection loss, or ambiguous admission response permanently switches that local run to status-only recovery; status-read failures may be polled only within the configured wait window and never cause a second admission or fallback to dev or the legacy whole-plan RPC. The default status polling interval is 10 seconds.
|
|
386
|
+
|
|
387
|
+
Success requires the terminal database proof and independent RLS readback to agree on the approved execution, exact row/exchange/audit closure, and exactly 50 derivative targets split into 23 flows and 27 processes. `pending`, `failed`, and `indeterminate` all return a non-zero exit status. The protected operation keeps all affected rows private to their owner, changes no `state_code`, and does not publish data.
|
|
388
|
+
|
|
357
389
|
For the derivative-only profile, use the same three commands with `--operation rebuild-derivatives`. Its scope must contain exactly one `processes` action with `action: "rebuild_derivatives"`, `target_mode: "owner_draft"`, expected current owner, expected `state_code: 0`, and the exact component set `extracted_md` plus `embedding_ft`.
|
|
358
390
|
|
|
359
391
|
`--page-size` accepts `1-5000` and is only the requested maximum. PostgREST may enforce a lower server-side cap. The CLI requests `Prefer: count=exact`, validates the exact total and returned range from each `Content-Range`, advances the next offset by the number of rows actually returned, and requires strict `id`/`version` ordering without missing or duplicate identities. Each accepted scan records per-table requested/effective page size, page count, rows fetched, exact total, and aggregate entity counts.
|
|
@@ -373,7 +405,7 @@ The scope is intentionally narrow:
|
|
|
373
405
|
|
|
374
406
|
`plan` accepts the account scan only after its exact-count proof is complete, then writes the frozen `maintenance-scope.json`, `rls-visible-snapshot.json`, `protected-rows.jsonl`, `reference-impact-report.json`, `maintenance-plan.json`, and `dry-run-report.json`. The snapshot, dry-run report, and newly generated plan carry the aggregate completeness proof, so it is bound into the plan SHA-256. Alias plans additionally write `exchange-rewrite-plan.jsonl`, freeze current-owner state-0 target FP, target UG, and source UG snapshots for each batch, derive schema-valid desired payloads with matching embedded UUID/version, and include the exact closure, `modified_at`, hashes, conversion evidence, and postconditions in the approved plan. A derivative rebuild plan additionally obtains a database-produced snapshot for only the exact target action and binds its primary and derivative preconditions into the plan; large markdown/vector fields are not added to the account-wide scan. The plan SHA-256 is the approval identity; do not edit or recompute the plan after review.
|
|
375
407
|
|
|
376
|
-
`apply` is write-disabled unless all three commit guards are present: `--commit`, `--approve-plan <sha256>`, and `--confirm <current-account-email>`. Before approval is persisted or any write runs, it requires a fresh complete exact-count account scan and re-checks the whole plan for drift; the current completeness proof is recorded in `approval-record.json`. Ordinary draft updates/deletes use their platform paths. The
|
|
408
|
+
`apply` is write-disabled unless all three commit guards are present: `--commit`, `--approve-plan <sha256>`, and `--confirm <current-account-email>`. Before approval is persisted or any write runs, it requires a fresh complete exact-count account scan and re-checks the whole plan for drift; the current completeness proof is recorded in `approval-record.json`. Ordinary draft updates/deletes use their platform paths. The original V1 alias adapter retains its frozen request and artifact contract for compatibility, but it is not an authorized execution or recovery fallback for a sealed production `merge-support-aliases` plan. That plan must use `run-protected`, whose database contract replaces replay with one durable attempt/admission identity.
|
|
377
409
|
|
|
378
410
|
For `rebuild-derivatives`, apply submits the frozen single-action plan only to the authenticated guarded RPC. The database admission envelope must report `queued`; the CLI records that durable admission as an `accepted` action with queued proof. It does not mean markdown or embedding generation has completed. Replay must return the same durable request/proof rather than enqueueing a second rebuild. There is no fallback to a direct Edge call, `admin embedding-run`, a raw queue, SQL, service-role credentials, or raw REST mutation.
|
|
379
411
|
|
package/dist/src/cli.js
CHANGED
|
@@ -56,6 +56,7 @@ import { runDatasetClassificationApply, runDatasetClassificationAudit, runDatase
|
|
|
56
56
|
import { runDatasetMaintenanceClearAccount, } from './lib/dataset-maintenance-clear-account.js';
|
|
57
57
|
import { runDatasetMaintenancePlan } from './lib/dataset-maintenance-plan.js';
|
|
58
58
|
import { runDatasetMaintenanceApply } from './lib/dataset-maintenance-apply.js';
|
|
59
|
+
import { runDatasetMaintenanceProtected } from './lib/dataset-maintenance-protected-run.js';
|
|
59
60
|
import { runDatasetMaintenanceVerify } from './lib/dataset-maintenance-verify.js';
|
|
60
61
|
import { runDatasetSourceUploadAttachments, } from './lib/dataset-source-upload-attachments.js';
|
|
61
62
|
function renderMainHelp(dotEnvStatus) {
|
|
@@ -131,6 +132,7 @@ Examples:
|
|
|
131
132
|
tiangong-lca dataset references rewrite --input ./rows.jsonl --from flow:<old-id>@<old-version> --to flow:<new-id>@<new-version> --out-dir /abs/path/to/dataset-rewrite
|
|
132
133
|
tiangong-lca dataset maintenance clear-account --out-dir /abs/path/to/account-clear --json
|
|
133
134
|
tiangong-lca dataset maintenance plan --scope ./maintenance-scope.json --operation merge-support-aliases --out-dir /abs/path/to/dataset-maintenance
|
|
135
|
+
tiangong-lca dataset maintenance run-protected --plan ./maintenance-plan.json --freeze ./protected-execution-seal.json --approval ./protected-approval.json --out-dir /abs/path/to/protected-run --status-only
|
|
134
136
|
tiangong-lca lifecyclemodel auto-build --input ./lifecyclemodel-auto-build.request.json --out-dir /abs/path/to/lifecyclemodel-run
|
|
135
137
|
tiangong-lca lifecyclemodel validate-build --run-dir /abs/path/to/lifecyclemodel-run
|
|
136
138
|
tiangong-lca lifecyclemodel publish-build --run-dir /abs/path/to/lifecyclemodel-run
|
|
@@ -283,6 +285,7 @@ Implemented Subcommands:
|
|
|
283
285
|
maintenance clear-account Dry-run or clear current authenticated account-owned dataset rows through RLS
|
|
284
286
|
maintenance plan Build an immutable, RLS-visible row-level maintenance plan
|
|
285
287
|
maintenance apply Execute an explicitly approved maintenance plan through current-user RLS
|
|
288
|
+
maintenance run-protected Run or inspect one sealed, one-shot production maintenance execution
|
|
286
289
|
maintenance verify Read back affected rows and references against the immutable plan
|
|
287
290
|
|
|
288
291
|
Examples:
|
|
@@ -310,21 +313,25 @@ Examples:
|
|
|
310
313
|
tiangong-lca dataset references refresh-remote --input ./rows.jsonl --out ./rows.refreshed.jsonl --out-dir ./dataset-reference-refresh --help
|
|
311
314
|
tiangong-lca dataset maintenance clear-account --out-dir ./account-clear --json --help
|
|
312
315
|
tiangong-lca dataset maintenance plan --scope ./maintenance-scope.json --operation merge-support-aliases --out-dir ./dataset-maintenance --help
|
|
316
|
+
tiangong-lca dataset maintenance run-protected --help
|
|
313
317
|
`.trim();
|
|
314
318
|
}
|
|
315
319
|
function renderDatasetMaintenanceHelp() {
|
|
316
320
|
return `Usage:
|
|
317
|
-
tiangong-lca dataset maintenance <clear-account|plan|apply|verify> [options]
|
|
321
|
+
tiangong-lca dataset maintenance <clear-account|plan|apply|run-protected|verify> [options]
|
|
318
322
|
|
|
319
323
|
Actions:
|
|
320
324
|
clear-account Dry-run or delete current authenticated account-owned lifecyclemodels, processes, flows, sources, and contacts.
|
|
321
325
|
plan Build an immutable maintenance plan from a scope manifest, visible remote snapshot, dependency impact report, and intended operation.
|
|
322
|
-
apply Execute or durably admit an approved plan through current-user RLS and platform dataset command paths
|
|
326
|
+
apply Execute or durably admit an ordinary approved plan through current-user RLS and platform dataset command paths.
|
|
327
|
+
run-protected Run or inspect one sealed production execution with one-shot admission and terminal derivative proof.
|
|
323
328
|
verify Re-fetch rows, references, or derivative request state and report passed, pending, or failed independently of apply.
|
|
324
329
|
|
|
325
330
|
Safety:
|
|
326
331
|
plan and verify are read-only.
|
|
327
332
|
apply is commit-only and requires --commit, the exact plan SHA-256 via --approve-plan, and the current account email via --confirm.
|
|
333
|
+
A sealed production merge-support-aliases execution must use run-protected; apply is not its fallback.
|
|
334
|
+
run-protected is production-only: authenticated owner context plus server-side actor/user_id/state_code=0 and exact-plan closure fences protect writes; RLS remains a defense on public and independent-read surfaces. It never falls back to dev, a legacy alias RPC, or a second admission POST.
|
|
328
335
|
|
|
329
336
|
Required Artifact Contract:
|
|
330
337
|
- maintenance-plan.json
|
|
@@ -334,13 +341,15 @@ Required Artifact Contract:
|
|
|
334
341
|
- dry-run-report.json
|
|
335
342
|
- commit-report.json
|
|
336
343
|
- readback-verify-report.json
|
|
344
|
+
run-protected uses a separate immutable protected-execution seal, submission marker, append-only status ledger, and terminal report.
|
|
337
345
|
|
|
338
346
|
Examples:
|
|
339
347
|
tiangong-lca dataset maintenance clear-account --out-dir ./account-clear --json
|
|
340
348
|
tiangong-lca dataset maintenance clear-account --commit --confirm user@example.com --out-dir ./account-clear
|
|
341
|
-
tiangong-lca dataset maintenance plan --scope ./maintenance-scope.json --operation
|
|
349
|
+
tiangong-lca dataset maintenance plan --scope ./maintenance-scope.json --operation repair-references --out-dir ./dataset-maintenance
|
|
342
350
|
tiangong-lca dataset maintenance plan --scope ./derivative-rebuild-scope.json --operation rebuild-derivatives --out-dir ./derivative-rebuild
|
|
343
351
|
tiangong-lca dataset maintenance apply --plan ./dataset-maintenance/maintenance-plan.json --commit --approve-plan <sha256> --confirm user@example.com
|
|
352
|
+
tiangong-lca dataset maintenance run-protected --plan ./maintenance-plan.json --freeze ./protected-execution-seal.json --approval ./protected-approval.json --out-dir ./protected-run --status-only
|
|
344
353
|
tiangong-lca dataset maintenance verify --plan ./dataset-maintenance/maintenance-plan.json --out-dir ./dataset-maintenance/verify
|
|
345
354
|
`.trim();
|
|
346
355
|
}
|
|
@@ -373,6 +382,7 @@ Behavior:
|
|
|
373
382
|
Commit-only. The command rejects dry-run mode, a missing --commit flag, a plan hash mismatch,
|
|
374
383
|
or a confirmation email that does not match the current authenticated account.
|
|
375
384
|
For rebuild-derivatives, success means guarded admission is queued; it never means derivatives completed.
|
|
385
|
+
Sealed production merge-support-aliases executions must use run-protected; this command is not a fallback.
|
|
376
386
|
|
|
377
387
|
Options:
|
|
378
388
|
--plan <file> Immutable maintenance-plan.json
|
|
@@ -386,6 +396,45 @@ Options:
|
|
|
386
396
|
Outputs include approval-record.json and commit-report.json alongside an append-only action or admission ledger.
|
|
387
397
|
`.trim();
|
|
388
398
|
}
|
|
399
|
+
function renderDatasetMaintenanceRunProtectedHelp() {
|
|
400
|
+
return `Usage:
|
|
401
|
+
tiangong-lca dataset maintenance run-protected --plan <file> --freeze <file> --approval <file> --out-dir <dir> --commit --approve-execution <sha256> --confirm <email> [options]
|
|
402
|
+
tiangong-lca dataset maintenance run-protected --plan <file> --freeze <file> --approval <file> --out-dir <dir> --status-only [options]
|
|
403
|
+
|
|
404
|
+
Behavior:
|
|
405
|
+
Runs one sealed, server-dispatched production maintenance execution fenced to the authenticated actor's
|
|
406
|
+
exact owner-draft target set, or reads durable status through an auth.uid-, actor-, and plan-fenced RPC
|
|
407
|
+
without admitting work; only the independent table readback uses RLS.
|
|
408
|
+
Commit and status-only modes are mutually exclusive. The commit path validates the full private
|
|
409
|
+
before-state, accepts only server-derived gates within the 180-second preflight window, writes an immutable
|
|
410
|
+
local submission marker, and sends at most one admission POST. After a marker or ambiguous response,
|
|
411
|
+
use --status-only; the command never retries admission or falls back to dev or the legacy alias RPC.
|
|
412
|
+
|
|
413
|
+
Required in both modes:
|
|
414
|
+
--plan <file> Immutable maintenance-plan.json
|
|
415
|
+
--freeze <file> Protected production execution seal/freeze artifact
|
|
416
|
+
--approval <file> Exact human-approval binding artifact
|
|
417
|
+
--out-dir <dir> Private protected-run artifact directory
|
|
418
|
+
|
|
419
|
+
Commit-only guards:
|
|
420
|
+
--commit Submit the sealed execution exactly once
|
|
421
|
+
--approve-execution <sha256> Exact approved execution identity SHA-256
|
|
422
|
+
--confirm <email> Current authenticated account email
|
|
423
|
+
|
|
424
|
+
Recovery:
|
|
425
|
+
--status-only Read/poll and independently verify the sealed request; never preflight or admit
|
|
426
|
+
|
|
427
|
+
Options:
|
|
428
|
+
--wait-seconds <n> Maximum terminal-status wait in seconds; 0 performs one status read
|
|
429
|
+
--poll-ms <n> Positive polling interval in milliseconds; default 10000
|
|
430
|
+
--page-size <n> Requested RLS readback page size, 1-5000
|
|
431
|
+
--timeout-ms <n> Positive request timeout in milliseconds
|
|
432
|
+
--json Print compact JSON
|
|
433
|
+
-h, --help
|
|
434
|
+
|
|
435
|
+
Only a terminal passed proof exits successfully. pending, failed, and indeterminate return non-zero.
|
|
436
|
+
`.trim();
|
|
437
|
+
}
|
|
389
438
|
function renderDatasetMaintenanceVerifyHelp() {
|
|
390
439
|
return `Usage:
|
|
391
440
|
tiangong-lca dataset maintenance verify --plan <file> [options]
|
|
@@ -3040,6 +3089,19 @@ function parseDatasetMaintenancePositiveInteger(value, flagName) {
|
|
|
3040
3089
|
}
|
|
3041
3090
|
return Number.parseInt(value.trim(), 10);
|
|
3042
3091
|
}
|
|
3092
|
+
function parseDatasetMaintenanceNonNegativeInteger(value, flagName) {
|
|
3093
|
+
if (typeof value !== 'string') {
|
|
3094
|
+
return undefined;
|
|
3095
|
+
}
|
|
3096
|
+
if (!/^\d+$/u.test(value.trim())) {
|
|
3097
|
+
throw new CliError(`${flagName} must be a non-negative integer.`, {
|
|
3098
|
+
code: 'DATASET_MAINTENANCE_INTEGER_INVALID',
|
|
3099
|
+
exitCode: 2,
|
|
3100
|
+
details: { flag: flagName, value },
|
|
3101
|
+
});
|
|
3102
|
+
}
|
|
3103
|
+
return Number.parseInt(value.trim(), 10);
|
|
3104
|
+
}
|
|
3043
3105
|
function parseDatasetMaintenancePlanFlags(args) {
|
|
3044
3106
|
let values;
|
|
3045
3107
|
try {
|
|
@@ -3126,6 +3188,54 @@ function parseDatasetMaintenanceApplyFlags(args) {
|
|
|
3126
3188
|
dryRun: Boolean(values['dry-run']),
|
|
3127
3189
|
};
|
|
3128
3190
|
}
|
|
3191
|
+
function parseDatasetMaintenanceProtectedFlags(args) {
|
|
3192
|
+
let values;
|
|
3193
|
+
try {
|
|
3194
|
+
({ values } = parseArgs({
|
|
3195
|
+
args,
|
|
3196
|
+
allowPositionals: false,
|
|
3197
|
+
strict: true,
|
|
3198
|
+
options: {
|
|
3199
|
+
help: { type: 'boolean', short: 'h' },
|
|
3200
|
+
json: { type: 'boolean' },
|
|
3201
|
+
plan: { type: 'string' },
|
|
3202
|
+
freeze: { type: 'string' },
|
|
3203
|
+
approval: { type: 'string' },
|
|
3204
|
+
'out-dir': { type: 'string' },
|
|
3205
|
+
commit: { type: 'boolean' },
|
|
3206
|
+
'status-only': { type: 'boolean' },
|
|
3207
|
+
'approve-execution': { type: 'string' },
|
|
3208
|
+
confirm: { type: 'string' },
|
|
3209
|
+
'wait-seconds': { type: 'string' },
|
|
3210
|
+
'poll-ms': { type: 'string' },
|
|
3211
|
+
'page-size': { type: 'string' },
|
|
3212
|
+
'timeout-ms': { type: 'string' },
|
|
3213
|
+
},
|
|
3214
|
+
}));
|
|
3215
|
+
}
|
|
3216
|
+
catch (error) {
|
|
3217
|
+
throw new CliError(String(error), {
|
|
3218
|
+
code: 'INVALID_ARGS',
|
|
3219
|
+
exitCode: 2,
|
|
3220
|
+
});
|
|
3221
|
+
}
|
|
3222
|
+
return {
|
|
3223
|
+
help: Boolean(values.help),
|
|
3224
|
+
json: Boolean(values.json),
|
|
3225
|
+
planPath: typeof values.plan === 'string' ? values.plan : '',
|
|
3226
|
+
freezePath: typeof values.freeze === 'string' ? values.freeze : '',
|
|
3227
|
+
approvalPath: typeof values.approval === 'string' ? values.approval : '',
|
|
3228
|
+
outDir: typeof values['out-dir'] === 'string' ? values['out-dir'] : '',
|
|
3229
|
+
commit: Boolean(values.commit),
|
|
3230
|
+
statusOnly: Boolean(values['status-only']),
|
|
3231
|
+
approveExecution: typeof values['approve-execution'] === 'string' ? values['approve-execution'] : undefined,
|
|
3232
|
+
confirm: typeof values.confirm === 'string' ? values.confirm : undefined,
|
|
3233
|
+
waitSeconds: parseDatasetMaintenanceNonNegativeInteger(values['wait-seconds'], '--wait-seconds'),
|
|
3234
|
+
pollMs: parseDatasetMaintenancePositiveInteger(values['poll-ms'], '--poll-ms'),
|
|
3235
|
+
pageSize: parseDatasetMaintenancePositiveInteger(values['page-size'], '--page-size'),
|
|
3236
|
+
timeoutMs: parseDatasetMaintenancePositiveInteger(values['timeout-ms'], '--timeout-ms'),
|
|
3237
|
+
};
|
|
3238
|
+
}
|
|
3129
3239
|
function parseDatasetMaintenanceVerifyFlags(args) {
|
|
3130
3240
|
let values;
|
|
3131
3241
|
try {
|
|
@@ -4905,6 +5015,7 @@ export async function executeCli(argv, deps) {
|
|
|
4905
5015
|
const datasetMaintenanceClearAccountImpl = deps.runDatasetMaintenanceClearAccountImpl ?? runDatasetMaintenanceClearAccount;
|
|
4906
5016
|
const datasetMaintenancePlanImpl = deps.runDatasetMaintenancePlanImpl ?? runDatasetMaintenancePlan;
|
|
4907
5017
|
const datasetMaintenanceApplyImpl = deps.runDatasetMaintenanceApplyImpl ?? runDatasetMaintenanceApply;
|
|
5018
|
+
const datasetMaintenanceProtectedImpl = deps.runDatasetMaintenanceProtectedImpl ?? runDatasetMaintenanceProtected;
|
|
4908
5019
|
const datasetMaintenanceVerifyImpl = deps.runDatasetMaintenanceVerifyImpl ?? runDatasetMaintenanceVerify;
|
|
4909
5020
|
const datasetSourceUploadAttachmentsImpl = deps.runDatasetSourceUploadAttachmentsImpl ?? runDatasetSourceUploadAttachments;
|
|
4910
5021
|
if (flags.version) {
|
|
@@ -5617,6 +5728,85 @@ export async function executeCli(argv, deps) {
|
|
|
5617
5728
|
stderr: '',
|
|
5618
5729
|
};
|
|
5619
5730
|
}
|
|
5731
|
+
if (action === 'run-protected') {
|
|
5732
|
+
const datasetFlags = parseDatasetMaintenanceProtectedFlags(commandArgs.slice(1));
|
|
5733
|
+
if (datasetFlags.help) {
|
|
5734
|
+
return {
|
|
5735
|
+
exitCode: 0,
|
|
5736
|
+
stdout: `${renderDatasetMaintenanceRunProtectedHelp()}\n`,
|
|
5737
|
+
stderr: '',
|
|
5738
|
+
};
|
|
5739
|
+
}
|
|
5740
|
+
if (!datasetFlags.planPath) {
|
|
5741
|
+
throw new CliError('dataset maintenance run-protected requires --plan.', {
|
|
5742
|
+
code: 'DATASET_MAINTENANCE_PROTECTED_PLAN_REQUIRED',
|
|
5743
|
+
exitCode: 2,
|
|
5744
|
+
});
|
|
5745
|
+
}
|
|
5746
|
+
if (!datasetFlags.freezePath) {
|
|
5747
|
+
throw new CliError('dataset maintenance run-protected requires --freeze.', {
|
|
5748
|
+
code: 'DATASET_MAINTENANCE_PROTECTED_FREEZE_REQUIRED',
|
|
5749
|
+
exitCode: 2,
|
|
5750
|
+
});
|
|
5751
|
+
}
|
|
5752
|
+
if (!datasetFlags.approvalPath) {
|
|
5753
|
+
throw new CliError('dataset maintenance run-protected requires --approval.', {
|
|
5754
|
+
code: 'DATASET_MAINTENANCE_PROTECTED_APPROVAL_FILE_REQUIRED',
|
|
5755
|
+
exitCode: 2,
|
|
5756
|
+
});
|
|
5757
|
+
}
|
|
5758
|
+
if (!datasetFlags.outDir) {
|
|
5759
|
+
throw new CliError('dataset maintenance run-protected requires --out-dir.', {
|
|
5760
|
+
code: 'DATASET_MAINTENANCE_PROTECTED_OUT_DIR_REQUIRED',
|
|
5761
|
+
exitCode: 2,
|
|
5762
|
+
});
|
|
5763
|
+
}
|
|
5764
|
+
if (datasetFlags.commit && datasetFlags.statusOnly) {
|
|
5765
|
+
throw new CliError('Cannot pass both --commit and --status-only.', {
|
|
5766
|
+
code: 'DATASET_MAINTENANCE_PROTECTED_MODE_CONFLICT',
|
|
5767
|
+
exitCode: 2,
|
|
5768
|
+
});
|
|
5769
|
+
}
|
|
5770
|
+
if (!datasetFlags.commit && !datasetFlags.statusOnly) {
|
|
5771
|
+
throw new CliError('dataset maintenance run-protected requires either --commit or --status-only.', {
|
|
5772
|
+
code: 'DATASET_MAINTENANCE_PROTECTED_MODE_REQUIRED',
|
|
5773
|
+
exitCode: 2,
|
|
5774
|
+
});
|
|
5775
|
+
}
|
|
5776
|
+
if (datasetFlags.commit && !datasetFlags.approveExecution) {
|
|
5777
|
+
throw new CliError('dataset maintenance run-protected requires --approve-execution <sha256> with --commit.', {
|
|
5778
|
+
code: 'DATASET_MAINTENANCE_PROTECTED_APPROVAL_REQUIRED',
|
|
5779
|
+
exitCode: 2,
|
|
5780
|
+
});
|
|
5781
|
+
}
|
|
5782
|
+
if (datasetFlags.commit && !datasetFlags.confirm) {
|
|
5783
|
+
throw new CliError('dataset maintenance run-protected requires --confirm <email> with --commit.', {
|
|
5784
|
+
code: 'DATASET_MAINTENANCE_PROTECTED_CONFIRM_REQUIRED',
|
|
5785
|
+
exitCode: 2,
|
|
5786
|
+
});
|
|
5787
|
+
}
|
|
5788
|
+
const report = await datasetMaintenanceProtectedImpl({
|
|
5789
|
+
planPath: datasetFlags.planPath,
|
|
5790
|
+
freezePath: datasetFlags.freezePath,
|
|
5791
|
+
approvalPath: datasetFlags.approvalPath,
|
|
5792
|
+
outDir: datasetFlags.outDir,
|
|
5793
|
+
commit: datasetFlags.commit,
|
|
5794
|
+
statusOnly: datasetFlags.statusOnly,
|
|
5795
|
+
approveExecution: datasetFlags.approveExecution,
|
|
5796
|
+
confirm: datasetFlags.confirm,
|
|
5797
|
+
waitSeconds: datasetFlags.waitSeconds,
|
|
5798
|
+
pollMs: datasetFlags.pollMs,
|
|
5799
|
+
pageSize: datasetFlags.pageSize,
|
|
5800
|
+
timeoutMs: datasetFlags.timeoutMs,
|
|
5801
|
+
env: deps.env,
|
|
5802
|
+
fetchImpl: deps.fetchImpl,
|
|
5803
|
+
});
|
|
5804
|
+
return {
|
|
5805
|
+
exitCode: report.status === 'passed' ? 0 : 1,
|
|
5806
|
+
stdout: stringifyJson(report, datasetFlags.json),
|
|
5807
|
+
stderr: '',
|
|
5808
|
+
};
|
|
5809
|
+
}
|
|
5620
5810
|
if (action === 'verify') {
|
|
5621
5811
|
const datasetFlags = parseDatasetMaintenanceVerifyFlags(commandArgs.slice(1));
|
|
5622
5812
|
if (datasetFlags.help) {
|
|
@@ -5646,7 +5836,7 @@ export async function executeCli(argv, deps) {
|
|
|
5646
5836
|
stderr: '',
|
|
5647
5837
|
};
|
|
5648
5838
|
}
|
|
5649
|
-
throw new CliError("dataset maintenance action must be 'clear-account', 'plan', 'apply', or 'verify'.", {
|
|
5839
|
+
throw new CliError("dataset maintenance action must be 'clear-account', 'plan', 'apply', 'run-protected', or 'verify'.", {
|
|
5650
5840
|
code: 'DATASET_MAINTENANCE_ACTION_INVALID',
|
|
5651
5841
|
exitCode: 2,
|
|
5652
5842
|
});
|