enigma-memory 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +55 -0
- package/README.md +379 -0
- package/apps/cli/bin/enigma.mjs +1117 -0
- package/apps/desktop/src/app.js +1327 -0
- package/apps/desktop/src/index.html +1373 -0
- package/apps/desktop/src/styles.css +386 -0
- package/apps/gateway/bin/enigma-gateway.mjs +52 -0
- package/apps/gateway/src/server.mjs +1403 -0
- package/apps/native-host/README.md +265 -0
- package/apps/native-host/bin/enigma-native-host.mjs +499 -0
- package/apps/native-host/manifests/com.enigma.native_host.chrome.json +9 -0
- package/apps/native-host/manifests/com.enigma.native_host.edge.json +9 -0
- package/apps/native-host/manifests/com.enigma.native_host.firefox.json +9 -0
- package/apps/relay/bin/enigma-relay.mjs +52 -0
- package/apps/relay/src/server.mjs +1571 -0
- package/apps/verifier/bin/enigma-verify.mjs +240 -0
- package/deploy/docker-compose.production.example.yml +150 -0
- package/deploy/kubernetes/enigma-backend.example.yaml +580 -0
- package/package.json +196 -0
- package/packages/adapters/PACKAGE_CONTRACT.md +47 -0
- package/packages/adapters/src/index.js +183 -0
- package/packages/boundary/src/index.js +468 -0
- package/packages/connectors/src/index.js +533 -0
- package/packages/core/src/index.js +766 -0
- package/packages/enterprise/src/index.js +505 -0
- package/packages/importers/src/index.js +1083 -0
- package/packages/mcp-server/bin/enigma-mcp.mjs +19 -0
- package/packages/mcp-server/src/index.js +1185 -0
- package/packages/mesh/src/index.js +531 -0
- package/packages/metering/PACKAGE_CONTRACT.md +20 -0
- package/packages/metering/src/index.js +246 -0
- package/packages/optimizer/src/index.js +707 -0
- package/packages/passport/src/index.js +651 -0
- package/packages/settlement/PACKAGE_CONTRACT.md +28 -0
- package/packages/settlement/src/index.js +369 -0
- package/packages/storage/PACKAGE_CONTRACT.md +23 -0
- package/packages/storage/src/index.js +392 -0
- package/packages/vault/src/index.js +904 -0
- package/scripts/build-ai-orchestration-plan.mjs +248 -0
- package/scripts/build-cloudflare-pages-release-packet.mjs +287 -0
- package/scripts/build-cloudflare-token-policy.mjs +239 -0
- package/scripts/build-cloudflare-token-request.mjs +314 -0
- package/scripts/build-demo-assets.mjs +263 -0
- package/scripts/build-edge-backend-workers.mjs +353 -0
- package/scripts/build-goal-completion-audit.mjs +398 -0
- package/scripts/build-hosted-probe-worker.mjs +191 -0
- package/scripts/build-operator-acceptance-packet.mjs +254 -0
- package/scripts/build-operator-evidence-starter.mjs +525 -0
- package/scripts/build-production-backend-env-kit.mjs +384 -0
- package/scripts/build-production-dependency-report.mjs +369 -0
- package/scripts/build-production-handoff-packet.mjs +475 -0
- package/scripts/build-production-readiness-manifest.mjs +209 -0
- package/scripts/build-production-status-board.mjs +297 -0
- package/scripts/build-production-storage-migration.mjs +86 -0
- package/scripts/build-production-workplan.mjs +371 -0
- package/scripts/build-review-packet.mjs +594 -0
- package/scripts/check.mjs +419 -0
- package/scripts/cloudflare-ops.mjs +1672 -0
- package/scripts/cloudflare-secret-env.mjs +128 -0
- package/scripts/collect-hosted-backend-live-evidence.mjs +263 -0
- package/scripts/infrastructure-readiness.mjs +944 -0
- package/scripts/install-enigma-local.mjs +270 -0
- package/scripts/memory-optimization-benchmark.mjs +242 -0
- package/scripts/monitor-live-endpoints.mjs +358 -0
- package/scripts/release-audit.mjs +5588 -0
- package/scripts/release-provenance.mjs +250 -0
- package/scripts/run-backend-readiness-smoke.mjs +220 -0
- package/scripts/validate-backup-restore-drill.mjs +166 -0
- package/scripts/validate-cloudflare-credentials.mjs +112 -0
- package/scripts/validate-cloudflare-worker-inspect.mjs +179 -0
- package/scripts/validate-domain-tls.mjs +248 -0
- package/scripts/validate-hosted-backend-live.mjs +319 -0
- package/scripts/validate-incident-drill.mjs +221 -0
- package/scripts/validate-kms-custody.mjs +235 -0
- package/scripts/validate-legal-compliance-approval.mjs +274 -0
- package/scripts/validate-monitoring-alerting.mjs +263 -0
- package/scripts/validate-network-access-policy.mjs +285 -0
- package/scripts/validate-operator-acceptance.mjs +298 -0
- package/scripts/validate-production-manifests.mjs +325 -0
- package/scripts/validate-public-site-security.mjs +252 -0
- package/scripts/validate-security-threat-model.mjs +285 -0
- package/scripts/validate-service-settlement.mjs +256 -0
- package/scripts/validate-support-sla.mjs +190 -0
- package/scripts/validate-tenant-policy-approval.mjs +228 -0
- package/scripts/validate-usage-metering.mjs +224 -0
- package/scripts/validate-whitepaper-claims.mjs +166 -0
- package/specs/boundary-manifest-v1.schema.json +35 -0
- package/specs/capsule-v1.schema.json +55 -0
- package/specs/claim-boundary-manifest-v1.schema.json +22 -0
- package/specs/connector-profile-v1.schema.json +62 -0
- package/specs/deletion-tombstone-v1.schema.json +26 -0
- package/specs/enterprise-policy-v1.schema.json +59 -0
- package/specs/gateway-request-v1.schema.json +32 -0
- package/specs/goal-completion-audit-v1.schema.json +70 -0
- package/specs/hosted-backend-live-evidence-v1.schema.json +147 -0
- package/specs/import-report-v1.schema.json +214 -0
- package/specs/infrastructure-readiness-manifest-v1.schema.json +130 -0
- package/specs/memory-event-v1.schema.json +42 -0
- package/specs/mesh-node-v1.schema.json +126 -0
- package/specs/passport-v1.schema.json +50 -0
- package/specs/production-handoff-packet-v1.schema.json +149 -0
- package/specs/receipt-v1.schema.json +61 -0
- package/specs/relay-record-v1.schema.json +43 -0
- package/specs/state-checkpoint-v1.schema.json +37 -0
- package/specs/trust-bundle-v1.schema.json +56 -0
|
@@ -0,0 +1,525 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { mkdir, writeFile } from 'node:fs/promises';
|
|
3
|
+
import { join, resolve } from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
import { buildOperatorAcceptancePacket } from './build-operator-acceptance-packet.mjs';
|
|
6
|
+
import { buildProductionReadinessManifest } from './build-production-readiness-manifest.mjs';
|
|
7
|
+
import { HOSTED_BACKEND_LIVE_EVIDENCE_SCHEMA, REQUIRED_REF_KEYS } from './validate-hosted-backend-live.mjs';
|
|
8
|
+
import { REQUIRED_EVIDENCE_ITEMS, REQUIRED_OWNER_ROLES, REQUIRED_PACKET_METADATA } from './validate-operator-acceptance.mjs';
|
|
9
|
+
import { groupHostedRefsByWorkstream } from './hosted-ref-workstreams.mjs';
|
|
10
|
+
|
|
11
|
+
export const OPERATOR_EVIDENCE_STARTER_SCHEMA = 'enigma.operator_evidence_starter.v1';
|
|
12
|
+
export const OPERATOR_EVIDENCE_FILL_PLAN_SCHEMA = 'enigma.operator_evidence_fill_plan.v1';
|
|
13
|
+
export const OPERATOR_HOSTED_REF_CATALOG_SCHEMA = 'enigma.operator_hosted_ref_catalog.v1';
|
|
14
|
+
export const OPERATOR_HOSTED_REF_WORKSTREAMS_SCHEMA = 'enigma.operator_hosted_ref_workstreams.v1';
|
|
15
|
+
|
|
16
|
+
const HOSTED_REF_KEYS = Object.freeze([...REQUIRED_REF_KEYS]);
|
|
17
|
+
|
|
18
|
+
function parseArgs(argv = process.argv.slice(2)) {
|
|
19
|
+
const out = { outDir: null, domain: 'enigmamemory.com', projectName: 'enigma-memory', environment: 'production', tenant: 'enigma-memory' };
|
|
20
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
21
|
+
const token = argv[index];
|
|
22
|
+
const next = () => {
|
|
23
|
+
const value = argv[index + 1];
|
|
24
|
+
if (typeof value !== 'string' || value.length === 0) throw new Error(`${token} requires a value`);
|
|
25
|
+
index += 1;
|
|
26
|
+
return value;
|
|
27
|
+
};
|
|
28
|
+
if (token === '--out-dir' || token === '--outDir') out.outDir = next();
|
|
29
|
+
else if (token === '--domain') out.domain = next();
|
|
30
|
+
else if (token === '--project-name' || token === '--projectName') out.projectName = next();
|
|
31
|
+
else if (token === '--environment') out.environment = next();
|
|
32
|
+
else if (token === '--tenant') out.tenant = next();
|
|
33
|
+
else if (typeof token === 'string' && token.startsWith('--out-dir=')) out.outDir = token.slice('--out-dir='.length);
|
|
34
|
+
else if (typeof token === 'string' && token.startsWith('--domain=')) out.domain = token.slice('--domain='.length);
|
|
35
|
+
else if (typeof token === 'string' && token.startsWith('--project-name=')) out.projectName = token.slice('--project-name='.length);
|
|
36
|
+
else if (typeof token === 'string' && token.startsWith('--environment=')) out.environment = token.slice('--environment='.length);
|
|
37
|
+
else if (typeof token === 'string' && token.startsWith('--tenant=')) out.tenant = token.slice('--tenant='.length);
|
|
38
|
+
else if (token === '--help' || token === '-h') out.help = true;
|
|
39
|
+
else throw new Error(`Unknown operator evidence starter option: ${token}`);
|
|
40
|
+
}
|
|
41
|
+
return out;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function placeholderRef(key) {
|
|
45
|
+
return `<operator-provided-${key}-evidence-ref>`;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function operatorOwnerRefPlaceholder(role) {
|
|
49
|
+
return `<operator-provided-${role}-approval-ref>`;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function operatorEvidenceRefPlaceholder(item) {
|
|
53
|
+
return `<operator-provided-${item}-evidence-ref>`;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function buildOwnerApprovalRefsTemplate() {
|
|
57
|
+
return Object.fromEntries(REQUIRED_OWNER_ROLES.map((role) => [role, operatorOwnerRefPlaceholder(role)]));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function buildEvidenceRefsTemplate() {
|
|
61
|
+
return Object.fromEntries(REQUIRED_EVIDENCE_ITEMS.map((item) => [item, operatorEvidenceRefPlaceholder(item)]));
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function hostedProbeTemplate(service, check, domain) {
|
|
65
|
+
const serviceName = service === 'relay' ? 'enigma-relay' : 'enigma-gateway';
|
|
66
|
+
const body = {
|
|
67
|
+
service: serviceName,
|
|
68
|
+
ok: true,
|
|
69
|
+
};
|
|
70
|
+
if (check === 'readyz') {
|
|
71
|
+
body.missing_evidence_refs = [];
|
|
72
|
+
body.checks = [
|
|
73
|
+
{
|
|
74
|
+
name: '<public-readyz-check-name>',
|
|
75
|
+
ok: true,
|
|
76
|
+
ref: '<operator-provided-readyz-check-evidence-ref>',
|
|
77
|
+
},
|
|
78
|
+
];
|
|
79
|
+
}
|
|
80
|
+
return {
|
|
81
|
+
url: `https://${service}.${domain}/${check}`,
|
|
82
|
+
status_code: 200,
|
|
83
|
+
body,
|
|
84
|
+
observed_at: '<probe-observed-at-iso8601>',
|
|
85
|
+
response_hash: 'sha256:<operator-provided-response-body-sha256-hex>',
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function buildHostedBackendLiveEvidenceTemplate({ domain }) {
|
|
90
|
+
return {
|
|
91
|
+
schema: HOSTED_BACKEND_LIVE_EVIDENCE_SCHEMA,
|
|
92
|
+
observed_at: '<hosted-live-observed-at-iso8601>',
|
|
93
|
+
environment: {
|
|
94
|
+
domain,
|
|
95
|
+
environment_id: '<public-environment-id-or-slug>',
|
|
96
|
+
cloud_provider: '<cloud-provider-name>',
|
|
97
|
+
region: '<public-region-code>',
|
|
98
|
+
owner: '<operator-team-or-role>',
|
|
99
|
+
status: 'observed',
|
|
100
|
+
},
|
|
101
|
+
refs: Object.fromEntries(HOSTED_REF_KEYS.map((key) => [key, `<operator-provided-${key}-evidence-ref>`])),
|
|
102
|
+
probes: {
|
|
103
|
+
relay_livez: hostedProbeTemplate('relay', 'livez', domain),
|
|
104
|
+
relay_readyz: hostedProbeTemplate('relay', 'readyz', domain),
|
|
105
|
+
gateway_livez: hostedProbeTemplate('gateway', 'livez', domain),
|
|
106
|
+
gateway_readyz: hostedProbeTemplate('gateway', 'readyz', domain),
|
|
107
|
+
},
|
|
108
|
+
operator_acceptance: {
|
|
109
|
+
decision: 'go',
|
|
110
|
+
packet_ref: '<operator-acceptance-packet-ref>',
|
|
111
|
+
approved_at: '<operator-acceptance-approved-at-iso8601>',
|
|
112
|
+
approved_by: '<operator-acceptance-approver-role>',
|
|
113
|
+
},
|
|
114
|
+
claim_boundary: {
|
|
115
|
+
hosted_backend_live: true,
|
|
116
|
+
public_site_live: false,
|
|
117
|
+
cloudflare_credentials_claim: false,
|
|
118
|
+
token_roi_claim: false,
|
|
119
|
+
provider_deletion_claim: false,
|
|
120
|
+
model_forgetting_claim: false,
|
|
121
|
+
},
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const HOSTED_REF_CATALOG = Object.freeze({
|
|
126
|
+
backend_host: {
|
|
127
|
+
purpose: 'Relay and gateway production deployment identity.',
|
|
128
|
+
env_names: ['ENIGMA_BACKEND_HOST_REF', 'ENIGMA_RELAY_DEPLOYMENT_REF', 'ENIGMA_GATEWAY_DEPLOYMENT_REF'],
|
|
129
|
+
evidence_command: 'npm run production:manifests',
|
|
130
|
+
accepted_refs: ['deployment ticket', 'container image digest', 'orchestrator rollout id'],
|
|
131
|
+
},
|
|
132
|
+
dns_tls: {
|
|
133
|
+
purpose: 'Public DNS, TLS certificate, and domain ownership evidence.',
|
|
134
|
+
env_names: ['ENIGMA_DNS_TLS_REF', 'ENIGMA_TLS_REF'],
|
|
135
|
+
evidence_command: 'npm run production:domain -- --evidence <domain-tls.json>',
|
|
136
|
+
accepted_refs: ['certificate transparency record', 'DNS provider change ticket', 'domain TLS validation artifact'],
|
|
137
|
+
},
|
|
138
|
+
durable_storage: {
|
|
139
|
+
purpose: 'Durable external storage migration and backup-compatible persistence.',
|
|
140
|
+
env_names: ['ENIGMA_DURABLE_STORAGE_REF', 'ENIGMA_EXTERNAL_STORAGE_REF', 'ENIGMA_RELAY_STORAGE_REF', 'ENIGMA_GATEWAY_STORAGE_REF'],
|
|
141
|
+
evidence_command: 'npm run production:storage -- --out <evidence-dir>/production-storage-migration.json',
|
|
142
|
+
accepted_refs: ['migration artifact', 'database change ticket', 'storage readiness evidence'],
|
|
143
|
+
},
|
|
144
|
+
kms_or_secret_custody: {
|
|
145
|
+
purpose: 'Runtime secret custody without exportable private key material.',
|
|
146
|
+
env_names: ['ENIGMA_KMS_KEY_REF', 'ENIGMA_KMS_REF', 'ENIGMA_SECRETS_MANAGER_REF', 'ENIGMA_GATEWAY_SIGNER_REF'],
|
|
147
|
+
evidence_command: 'npm run production:kms -- --evidence <kms-custody.json>',
|
|
148
|
+
accepted_refs: ['KMS key id reference', 'secrets-manager custody ticket', 'non-exportable signer attestation'],
|
|
149
|
+
},
|
|
150
|
+
backup_restore: {
|
|
151
|
+
purpose: 'Backup target and restore plan coverage for production data.',
|
|
152
|
+
env_names: ['ENIGMA_BACKUP_TARGET_REF', 'ENIGMA_RESTORE_TARGET_REF'],
|
|
153
|
+
evidence_command: 'npm run production:backup-drill -- --evidence <backup-restore-drill.json>',
|
|
154
|
+
accepted_refs: ['backup policy ticket', 'restore target ref', 'backup restore drill artifact'],
|
|
155
|
+
},
|
|
156
|
+
monitoring: {
|
|
157
|
+
purpose: 'Production metrics, synthetics, and operator-visible health coverage.',
|
|
158
|
+
env_names: ['ENIGMA_MONITORING_REF', 'ENIGMA_RELAY_MONITORING_REF', 'ENIGMA_GATEWAY_MONITORING_REF'],
|
|
159
|
+
evidence_command: 'npm run production:monitoring -- --evidence <monitoring-alerting.json>',
|
|
160
|
+
accepted_refs: ['dashboard ref', 'synthetic monitor ref', 'alert routing evidence'],
|
|
161
|
+
},
|
|
162
|
+
siem_or_log_sink: {
|
|
163
|
+
purpose: 'Tamper-resistant operational audit sink without raw memory payload export.',
|
|
164
|
+
env_names: ['ENIGMA_SIEM_REF', 'ENIGMA_AUDIT_SINK_REF', 'ENIGMA_LOG_SINK_REF'],
|
|
165
|
+
evidence_command: 'npm run production:monitoring -- --evidence <monitoring-alerting.json>',
|
|
166
|
+
accepted_refs: ['SIEM sink ticket', 'audit log export evidence', 'log retention policy ref'],
|
|
167
|
+
},
|
|
168
|
+
operator_acceptance: {
|
|
169
|
+
purpose: 'Operator go/no-go packet for the exact tenant, domain, and environment.',
|
|
170
|
+
env_names: ['ENIGMA_OPERATOR_ACCEPTANCE_REF', 'ENIGMA_OPERATOR_ACCEPTANCE_EVIDENCE_URI'],
|
|
171
|
+
evidence_command: 'npm run production:acceptance -- --packet <operator-acceptance-packet.json>',
|
|
172
|
+
accepted_refs: ['operator acceptance packet id', 'approval ticket', 'evidence repository link'],
|
|
173
|
+
},
|
|
174
|
+
runtime_auth: {
|
|
175
|
+
purpose: 'Runtime service authentication for relay/gateway dependencies.',
|
|
176
|
+
env_names: ['ENIGMA_RUNTIME_AUTH_REF', 'ENIGMA_RELAY_RUNTIME_AUTH_REF', 'ENIGMA_PAIRED_CLIENT_AUTH_REF'],
|
|
177
|
+
evidence_command: 'npm run production:network -- --evidence <network-access-policy.json>',
|
|
178
|
+
accepted_refs: ['runtime auth policy ticket', 'paired-client auth evidence', 'access-control review'],
|
|
179
|
+
},
|
|
180
|
+
admin_auth: {
|
|
181
|
+
purpose: 'Administrative control-plane authentication and authorization.',
|
|
182
|
+
env_names: ['ENIGMA_ADMIN_AUTH_REF', 'ENIGMA_GATEWAY_ADMIN_AUTH_REF'],
|
|
183
|
+
evidence_command: 'npm run production:network -- --evidence <network-access-policy.json>',
|
|
184
|
+
accepted_refs: ['admin auth review', 'privileged access ticket', 'control-plane policy ref'],
|
|
185
|
+
},
|
|
186
|
+
data_plane_auth: {
|
|
187
|
+
purpose: 'End-user/data-plane authentication for gateway APIs.',
|
|
188
|
+
env_names: ['ENIGMA_DATA_PLANE_AUTH_REF', 'ENIGMA_GATEWAY_DATA_PLANE_AUTH_REF'],
|
|
189
|
+
evidence_command: 'npm run production:network -- --evidence <network-access-policy.json>',
|
|
190
|
+
accepted_refs: ['data-plane auth review', 'API access policy artifact', 'tenant auth evidence'],
|
|
191
|
+
},
|
|
192
|
+
network_access_policy: {
|
|
193
|
+
purpose: 'Fail-closed public/private route exposure policy.',
|
|
194
|
+
env_names: ['ENIGMA_NETWORK_ACCESS_POLICY_REF', 'ENIGMA_NETWORK_POLICY_REF'],
|
|
195
|
+
evidence_command: 'npm run production:network -- --evidence <network-access-policy.json>',
|
|
196
|
+
accepted_refs: ['network policy artifact', 'ingress review ticket', 'route exposure attestation'],
|
|
197
|
+
},
|
|
198
|
+
kms_custody: {
|
|
199
|
+
purpose: 'KMS custody controls for production keys and signer material.',
|
|
200
|
+
env_names: ['ENIGMA_KMS_CUSTODY_REF', 'ENIGMA_KEY_CUSTODY_REF'],
|
|
201
|
+
evidence_command: 'npm run production:kms -- --evidence <kms-custody.json>',
|
|
202
|
+
accepted_refs: ['KMS custody evidence', 'key-owner approval', 'rotation policy ref'],
|
|
203
|
+
},
|
|
204
|
+
tenant_policy_approval: {
|
|
205
|
+
purpose: 'Tenant-specific retention, region, deletion, and legal-hold policy approval.',
|
|
206
|
+
env_names: ['ENIGMA_TENANT_POLICY_APPROVAL_REF', 'ENIGMA_TENANT_POLICY_REF'],
|
|
207
|
+
evidence_command: 'npm run production:tenant-policy -- --evidence <tenant-policy-approval.json>',
|
|
208
|
+
accepted_refs: ['tenant policy approval', 'region/retention review', 'legal-hold policy ref'],
|
|
209
|
+
},
|
|
210
|
+
usage_metering: {
|
|
211
|
+
purpose: 'Usage metering evidence for memory optimizer/service billing boundaries.',
|
|
212
|
+
env_names: ['ENIGMA_USAGE_METERING_REF', 'ENIGMA_METERING_REF'],
|
|
213
|
+
evidence_command: 'npm run production:usage -- --evidence <usage-metering.json>',
|
|
214
|
+
accepted_refs: ['metering artifact', 'billing telemetry review', 'usage aggregation evidence'],
|
|
215
|
+
},
|
|
216
|
+
service_settlement: {
|
|
217
|
+
purpose: 'Permissionless access settlement receipts without decentralizing raw memory.',
|
|
218
|
+
env_names: ['ENIGMA_SERVICE_SETTLEMENT_REF', 'ENIGMA_SETTLEMENT_REF'],
|
|
219
|
+
evidence_command: 'npm run production:settlement -- --evidence <service-settlement.json>',
|
|
220
|
+
accepted_refs: ['settlement receipt batch', 'quote verification artifact', 'operator settlement ref'],
|
|
221
|
+
},
|
|
222
|
+
monitoring_alerting: {
|
|
223
|
+
purpose: 'Alert coverage, escalation routing, and synthetic probes.',
|
|
224
|
+
env_names: ['ENIGMA_MONITORING_ALERTING_REF', 'ENIGMA_ALERTING_EVIDENCE_REF'],
|
|
225
|
+
evidence_command: 'npm run production:monitoring -- --evidence <monitoring-alerting.json>',
|
|
226
|
+
accepted_refs: ['alert policy artifact', 'on-call route evidence', 'synthetic probe evidence'],
|
|
227
|
+
},
|
|
228
|
+
public_site_security: {
|
|
229
|
+
purpose: 'Static public site security, omission policy, and header validation.',
|
|
230
|
+
env_names: ['ENIGMA_PUBLIC_SITE_SECURITY_REF', 'ENIGMA_SITE_SECURITY_REF'],
|
|
231
|
+
evidence_command: 'npm run production:site -- --site <public-site-dir>',
|
|
232
|
+
accepted_refs: ['public site security result', 'review packet preflight', 'Cloudflare Pages artifact hash'],
|
|
233
|
+
},
|
|
234
|
+
security_threat_model: {
|
|
235
|
+
purpose: 'Reviewed security threat model with no accepted critical blockers.',
|
|
236
|
+
env_names: ['ENIGMA_SECURITY_THREAT_MODEL_REF', 'ENIGMA_THREAT_MODEL_REF'],
|
|
237
|
+
evidence_command: 'npm run production:threat-model -- --evidence <security-threat-model.json>',
|
|
238
|
+
accepted_refs: ['threat model artifact', 'security review approval', 'risk register ticket'],
|
|
239
|
+
},
|
|
240
|
+
legal_compliance_approval: {
|
|
241
|
+
purpose: 'Claim-bounded legal/privacy approval for launch and operator evidence.',
|
|
242
|
+
env_names: ['ENIGMA_LEGAL_COMPLIANCE_REF', 'ENIGMA_LEGAL_APPROVAL_REF', 'ENIGMA_LEGAL_COMPLIANCE_APPROVAL_REF'],
|
|
243
|
+
evidence_command: 'npm run production:legal -- --evidence <legal-compliance-approval.json>',
|
|
244
|
+
accepted_refs: ['legal approval ticket', 'privacy review evidence', 'claim-boundary approval'],
|
|
245
|
+
},
|
|
246
|
+
support_sla: {
|
|
247
|
+
purpose: 'Support ownership, SLO/SLA, escalation, and incident response coverage.',
|
|
248
|
+
env_names: ['ENIGMA_SUPPORT_SLA_REF'],
|
|
249
|
+
evidence_command: 'npm run production:sla -- --evidence <support-sla.json>',
|
|
250
|
+
accepted_refs: ['support SLA document', 'on-call rota ref', 'escalation policy ticket'],
|
|
251
|
+
},
|
|
252
|
+
incident_drill: {
|
|
253
|
+
purpose: 'Incident drill proving roles, timeline, communications, and remediation loop.',
|
|
254
|
+
env_names: ['ENIGMA_INCIDENT_DRILL_REF'],
|
|
255
|
+
evidence_command: 'npm run production:incident-drill -- --evidence <incident-drill.json>',
|
|
256
|
+
accepted_refs: ['incident drill artifact', 'tabletop report', 'postmortem exercise ticket'],
|
|
257
|
+
},
|
|
258
|
+
backup_restore_drill: {
|
|
259
|
+
purpose: 'Restore drill proving RPO/RTO and restored root consistency.',
|
|
260
|
+
env_names: ['ENIGMA_BACKUP_RESTORE_DRILL_REF'],
|
|
261
|
+
evidence_command: 'npm run production:backup-drill -- --evidence <backup-restore-drill.json>',
|
|
262
|
+
accepted_refs: ['restore drill artifact', 'RPO/RTO evidence', 'backup verification ticket'],
|
|
263
|
+
},
|
|
264
|
+
relay_deployment: {
|
|
265
|
+
purpose: 'Relay production deployment rollout evidence for the exact hosted target.',
|
|
266
|
+
env_names: ['ENIGMA_RELAY_DEPLOYMENT_REF', 'ENIGMA_RELAY_BACKEND_HOST_REF'],
|
|
267
|
+
evidence_command: 'npm run production:manifests',
|
|
268
|
+
accepted_refs: ['relay deployment rollout id', 'relay container image digest', 'relay release ticket'],
|
|
269
|
+
},
|
|
270
|
+
gateway_deployment: {
|
|
271
|
+
purpose: 'Gateway production deployment rollout evidence for the exact hosted target.',
|
|
272
|
+
env_names: ['ENIGMA_GATEWAY_DEPLOYMENT_REF', 'ENIGMA_GATEWAY_BACKEND_HOST_REF'],
|
|
273
|
+
evidence_command: 'npm run production:manifests',
|
|
274
|
+
accepted_refs: ['gateway deployment rollout id', 'gateway container image digest', 'gateway release ticket'],
|
|
275
|
+
},
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
function buildHostedRefCatalog({ generatedAt } = {}) {
|
|
279
|
+
return {
|
|
280
|
+
schema: OPERATOR_HOSTED_REF_CATALOG_SCHEMA,
|
|
281
|
+
generated_at: generatedAt ?? null,
|
|
282
|
+
status: 'template_only_blocked_until_verified_refs',
|
|
283
|
+
required_ref_count: HOSTED_REF_KEYS.length,
|
|
284
|
+
refs: Object.fromEntries(HOSTED_REF_KEYS.map((key) => [key, HOSTED_REF_CATALOG[key] ?? {
|
|
285
|
+
purpose: `Operator-provided evidence for ${key}.`,
|
|
286
|
+
env_names: [],
|
|
287
|
+
evidence_command: 'Attach operator evidence and rerun production:manifest.',
|
|
288
|
+
accepted_refs: ['operator approval ticket'],
|
|
289
|
+
}])),
|
|
290
|
+
fill_rule: 'Every hosted ref must resolve to a public-safe evidence URI, ticket id, artifact hash, or approved external reference with status verified before readiness can be live.',
|
|
291
|
+
forbidden_values: ['bearer tokens', 'private keys', 'credential-bearing URLs', 'raw memory', 'prompts', 'transcripts', 'provider responses', 'decrypted content'],
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
function buildHostedRefWorkstreams({ generatedAt, hostedRefCatalog }) {
|
|
296
|
+
const groups = groupHostedRefsByWorkstream(HOSTED_REF_KEYS);
|
|
297
|
+
return {
|
|
298
|
+
schema: OPERATOR_HOSTED_REF_WORKSTREAMS_SCHEMA,
|
|
299
|
+
generated_at: generatedAt ?? null,
|
|
300
|
+
status: 'template_only_blocked_until_verified_refs',
|
|
301
|
+
required_ref_count: HOSTED_REF_KEYS.length,
|
|
302
|
+
workstreams: Object.fromEntries(Object.entries(groups).map(([workstream, refs]) => [workstream, {
|
|
303
|
+
ref_count: refs.length,
|
|
304
|
+
refs: refs.map((key) => {
|
|
305
|
+
const entry = hostedRefCatalog.refs[key] ?? {};
|
|
306
|
+
return {
|
|
307
|
+
key,
|
|
308
|
+
purpose: typeof entry.purpose === 'string' ? entry.purpose : `Operator-provided evidence for ${key}.`,
|
|
309
|
+
env_names: Array.isArray(entry.env_names) ? entry.env_names : [],
|
|
310
|
+
evidence_command: typeof entry.evidence_command === 'string' ? entry.evidence_command : 'Attach operator evidence and rerun production:manifest.',
|
|
311
|
+
accepted_refs: Array.isArray(entry.accepted_refs) ? entry.accepted_refs : [],
|
|
312
|
+
template_value: placeholderRef(key),
|
|
313
|
+
};
|
|
314
|
+
}),
|
|
315
|
+
}])),
|
|
316
|
+
completion_rule: 'Every ref in every workstream must be filled in hosted-refs.json with a public-safe verified evidence reference before hosted-live readiness can pass.',
|
|
317
|
+
claim_boundary: [
|
|
318
|
+
'This workstream checklist is not deployment proof, operator approval, or hosted-live evidence.',
|
|
319
|
+
'Use it to divide external operator evidence collection; do not paste secrets, account ids, credential-bearing URLs, raw memory, prompts, transcripts, provider responses, or private keys.',
|
|
320
|
+
],
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
function commandPlan({ domain, projectName }) {
|
|
325
|
+
return {
|
|
326
|
+
write_release_audit: 'npm run release:audit -- --out ./.enigma/release-audit-current.json',
|
|
327
|
+
build_readiness_manifest: 'npm run production:manifest -- --out <evidence-dir>/infrastructure-readiness-manifest.json',
|
|
328
|
+
build_storage_migration: 'npm run production:storage -- --out <evidence-dir>/production-storage-migration.json',
|
|
329
|
+
verify_readiness_live: 'npm run infrastructure:readiness -- --manifest <evidence-dir>/infrastructure-readiness-manifest.json --live --cloudflare-live required',
|
|
330
|
+
collect_hosted_live: 'npm run production:hosted-collect -- --relay-url https://relay.<domain> --gateway-url https://gateway.<domain> --refs-json <evidence-dir>/hosted-refs.json --domain <domain> --environment-id <env-id> --cloud-provider <provider> --region <region> --owner <owner> --operator-decision go --operator-packet-ref <operator-packet-ref> --operator-approved-at <iso> --operator-approved-by <operator> --evidence-out <evidence-dir>/hosted-backend-live.json --out <evidence-dir>/hosted-backend-live-collection.json',
|
|
331
|
+
validate_hosted_live: 'npm run production:hosted-live -- --evidence <evidence-dir>/hosted-backend-live.json',
|
|
332
|
+
build_operator_packet: 'npm run production:acceptance:packet -- --out <evidence-dir>/operator-acceptance-packet.json --owners-json <evidence-dir>/owner-approval-refs.json --evidence-refs <evidence-dir>/evidence-refs.json --readiness <evidence-dir>/infrastructure-readiness-live.json --manifest <evidence-dir>/infrastructure-readiness-manifest.json --storage <evidence-dir>/production-storage-migration.json --release-audit ./.enigma/release-audit-current.json --production-manifests <evidence-dir>/production-manifests.json --decision go --tenant <tenant-id> --target-regions <regions> --requested-go-live-date <date> --evidence-repository <evidence-repository> --packet-owner <operator>',
|
|
333
|
+
validate_operator_acceptance: 'npm run production:acceptance -- --packet <operator-acceptance-packet.json>',
|
|
334
|
+
build_handoff: `npm run production:handoff -- --site <public-site-dir> --project-name ${projectName} --domain ${domain} --live-url https://${domain}/ --expect-title Enigma --infrastructure-readiness <infrastructure-readiness-live.json> --operator-acceptance-packet <operator-acceptance-packet.json> --release-audit ./.enigma/release-audit-current.json`,
|
|
335
|
+
build_goal_audit: `npm run production:goal-audit -- --site <public-site-dir> --project-name ${projectName} --domain ${domain} --live-url https://${domain}/ --expect-title Enigma --infrastructure-readiness <infrastructure-readiness-live.json> --operator-acceptance-packet <operator-acceptance-packet.json> --release-audit ./.enigma/release-audit-current.json`,
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
function buildAcceptanceFillPlan({ domain, projectName, environment, tenant, hostedRefCatalog }) {
|
|
340
|
+
return {
|
|
341
|
+
schema: OPERATOR_EVIDENCE_FILL_PLAN_SCHEMA,
|
|
342
|
+
status: 'template_only_blocked_until_filled',
|
|
343
|
+
target: { domain, project_name: projectName, environment, tenant },
|
|
344
|
+
generated_files: {
|
|
345
|
+
hosted_refs_template: 'hosted-refs.template.json',
|
|
346
|
+
hosted_refs_final: 'hosted-refs.json',
|
|
347
|
+
hosted_live_evidence_template: 'hosted-backend-live.template.json',
|
|
348
|
+
hosted_live_collection: 'hosted-backend-live-collection.json',
|
|
349
|
+
hosted_live_evidence: 'hosted-backend-live.json',
|
|
350
|
+
owner_approval_refs_template: 'owner-approval-refs.template.json',
|
|
351
|
+
owner_approval_refs_final: 'owner-approval-refs.json',
|
|
352
|
+
evidence_refs_template: 'evidence-refs.template.json',
|
|
353
|
+
evidence_refs_final: 'evidence-refs.json',
|
|
354
|
+
readiness_manifest_template: 'infrastructure-readiness-manifest.template.json',
|
|
355
|
+
readiness_manifest_final: 'infrastructure-readiness-manifest.json',
|
|
356
|
+
storage_migration_final: 'production-storage-migration.json',
|
|
357
|
+
operator_packet_template: 'operator-acceptance-packet.template.json',
|
|
358
|
+
operator_packet_final: 'operator-acceptance-packet.json',
|
|
359
|
+
hosted_ref_catalog: 'hosted-ref-catalog.json',
|
|
360
|
+
hosted_ref_workstreams: 'hosted-ref-workstreams.json',
|
|
361
|
+
},
|
|
362
|
+
fill_order: [
|
|
363
|
+
'Fill string values in hosted-refs.template.json and save the completed copy as hosted-refs.json.',
|
|
364
|
+
'Use hosted-ref-workstreams.json to assign deployment, security, resilience, operations, governance, and commercial evidence owners without copying the full catalog into status updates.',
|
|
365
|
+
'Use hosted-backend-live.template.json only as the schema reference for public-safe observed hosted live evidence.',
|
|
366
|
+
'Run commands.build_readiness_manifest and commands.build_storage_migration.',
|
|
367
|
+
'Run commands.verify_readiness_live after all required hosted refs point at deployed target-environment evidence.',
|
|
368
|
+
'Run commands.collect_hosted_live after relay/gateway public HTTPS probes are live; it writes hosted-backend-live-collection.json and hosted-backend-live.json.',
|
|
369
|
+
'Run commands.validate_hosted_live against the generated hosted-backend-live.json.',
|
|
370
|
+
'Fill owner-approval-refs.template.json and evidence-refs.template.json with public-safe approval/evidence references.',
|
|
371
|
+
'Build the final operator packet with production:acceptance:packet using --owners-json <evidence-dir>/owner-approval-refs.json, --evidence-refs <evidence-dir>/evidence-refs.json, and the completed readiness/manifest/storage/release evidence files.',
|
|
372
|
+
'Validate operator-acceptance-packet.json with commands.validate_operator_acceptance; any blocker means the packet is still not launch evidence.',
|
|
373
|
+
'Run commands.build_handoff and commands.build_goal_audit only after validate_operator_acceptance returns ok:true.',
|
|
374
|
+
],
|
|
375
|
+
accepted_values: {
|
|
376
|
+
metadata: { decision: ['go'] },
|
|
377
|
+
owners: { approval_status: ['approved'] },
|
|
378
|
+
evidence: { status: ['verified'] },
|
|
379
|
+
},
|
|
380
|
+
required_metadata: REQUIRED_PACKET_METADATA,
|
|
381
|
+
required_owner_roles: REQUIRED_OWNER_ROLES.map((role) => ({
|
|
382
|
+
role,
|
|
383
|
+
required_fields: ['name', 'organization', 'approval_ref', 'approval_status=approved'],
|
|
384
|
+
})),
|
|
385
|
+
required_evidence_items: REQUIRED_EVIDENCE_ITEMS.map((item) => ({
|
|
386
|
+
item,
|
|
387
|
+
required_fields: ['ref', 'status=verified', 'owner'],
|
|
388
|
+
})),
|
|
389
|
+
hosted_ref_catalog: {
|
|
390
|
+
schema: hostedRefCatalog.schema,
|
|
391
|
+
required_ref_count: hostedRefCatalog.required_ref_count,
|
|
392
|
+
ref_keys: Object.keys(hostedRefCatalog.refs),
|
|
393
|
+
},
|
|
394
|
+
claim_boundary: [
|
|
395
|
+
'This fill plan is not operator approval, hosted-live evidence, or deployment proof.',
|
|
396
|
+
'Refs must point at external evidence artifacts or tickets; never paste bearer tokens, private keys, DSNs with credentials, raw memory, prompts, transcripts, provider responses, or decrypted content.',
|
|
397
|
+
'A go packet is valid only for the exact domain, tenant, environment, and deployed infrastructure named in the packet.',
|
|
398
|
+
],
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
export async function buildOperatorEvidenceStarter(options = {}) {
|
|
403
|
+
const args = options.args ?? parseArgs(options.argv ?? []);
|
|
404
|
+
const generatedAt = options.generated_at ?? options.generatedAt ?? new Date(0).toISOString();
|
|
405
|
+
const domain = args.domain ?? options.domain ?? 'enigmamemory.com';
|
|
406
|
+
const projectName = args.projectName ?? options.projectName ?? 'enigma-memory';
|
|
407
|
+
const environment = args.environment ?? options.environment ?? 'production';
|
|
408
|
+
const tenant = args.tenant ?? options.tenant ?? 'enigma-memory';
|
|
409
|
+
const hostedRefs = Object.fromEntries(HOSTED_REF_KEYS.map((key) => [key, placeholderRef(key)]));
|
|
410
|
+
const readinessManifest = await buildProductionReadinessManifest({
|
|
411
|
+
env: {
|
|
412
|
+
ENIGMA_PUBLIC_SITE_URL: `https://${domain}/`,
|
|
413
|
+
ENIGMA_CLOUDFLARE_PAGES_PROJECT_NAME: projectName,
|
|
414
|
+
ENIGMA_OPERATOR_DECISION: 'pending',
|
|
415
|
+
},
|
|
416
|
+
argv: ['--external-blocker', 'operator evidence starter has not been completed'],
|
|
417
|
+
generated_at: generatedAt,
|
|
418
|
+
});
|
|
419
|
+
const operatorPacket = await buildOperatorAcceptancePacket({
|
|
420
|
+
decision: 'blocked',
|
|
421
|
+
customer_or_tenant: tenant,
|
|
422
|
+
environment,
|
|
423
|
+
packet_id: `${tenant}-${environment}-starter`,
|
|
424
|
+
evidence_repository: '<operator-evidence-repository-or-ticket>',
|
|
425
|
+
packet_owner: '<operator-owner>',
|
|
426
|
+
last_updated: generatedAt,
|
|
427
|
+
});
|
|
428
|
+
const hostedRefCatalog = buildHostedRefCatalog({ generatedAt });
|
|
429
|
+
const hostedRefWorkstreams = buildHostedRefWorkstreams({ generatedAt, hostedRefCatalog });
|
|
430
|
+
const acceptanceFillPlan = buildAcceptanceFillPlan({ domain, projectName, environment, tenant, hostedRefCatalog });
|
|
431
|
+
const hostedBackendLiveEvidenceTemplate = buildHostedBackendLiveEvidenceTemplate({ domain });
|
|
432
|
+
const ownerApprovalRefsTemplate = buildOwnerApprovalRefsTemplate();
|
|
433
|
+
const evidenceRefsTemplate = buildEvidenceRefsTemplate();
|
|
434
|
+
const starter = {
|
|
435
|
+
schema: OPERATOR_EVIDENCE_STARTER_SCHEMA,
|
|
436
|
+
generated_at: generatedAt,
|
|
437
|
+
status: 'blocked_until_operator_evidence',
|
|
438
|
+
domain,
|
|
439
|
+
project_name: projectName,
|
|
440
|
+
environment,
|
|
441
|
+
tenant,
|
|
442
|
+
hosted_required_refs: hostedRefs,
|
|
443
|
+
hosted_ref_catalog: hostedRefCatalog,
|
|
444
|
+
hosted_ref_workstreams: hostedRefWorkstreams,
|
|
445
|
+
hosted_backend_live_evidence_template: hostedBackendLiveEvidenceTemplate,
|
|
446
|
+
owner_roles: REQUIRED_OWNER_ROLES,
|
|
447
|
+
evidence_items: REQUIRED_EVIDENCE_ITEMS,
|
|
448
|
+
readiness_manifest: readinessManifest,
|
|
449
|
+
operator_acceptance_packet: operatorPacket,
|
|
450
|
+
owner_approval_refs_template: ownerApprovalRefsTemplate,
|
|
451
|
+
evidence_refs_template: evidenceRefsTemplate,
|
|
452
|
+
commands: commandPlan({ domain, projectName }),
|
|
453
|
+
acceptance_fill_plan: acceptanceFillPlan,
|
|
454
|
+
counts: {
|
|
455
|
+
hosted_ref_count: HOSTED_REF_KEYS.length,
|
|
456
|
+
owner_role_count: REQUIRED_OWNER_ROLES.length,
|
|
457
|
+
evidence_item_count: REQUIRED_EVIDENCE_ITEMS.length,
|
|
458
|
+
current_blocker_count: readinessManifest.external_blockers.length,
|
|
459
|
+
acceptance_fill_step_count: acceptanceFillPlan.fill_order.length,
|
|
460
|
+
hosted_ref_catalog_count: hostedRefCatalog.required_ref_count,
|
|
461
|
+
hosted_ref_workstream_count: Object.keys(hostedRefWorkstreams.workstreams).length,
|
|
462
|
+
},
|
|
463
|
+
claim_boundary: [
|
|
464
|
+
'This starter is a public-safe checklist and template bundle, not production readiness evidence.',
|
|
465
|
+
'Do not paste bearer tokens, private keys, DSNs with credentials, raw memory, prompts, transcripts, provider responses, or decrypted content into these files.',
|
|
466
|
+
'Hosted/BYOC remains blocked until live relay/gateway probes, all refs, operator acceptance go, and current release audit evidence validate for the exact environment.',
|
|
467
|
+
],
|
|
468
|
+
};
|
|
469
|
+
return starter;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
export async function writeOperatorEvidenceStarter(starter, outDir) {
|
|
473
|
+
if (typeof outDir !== 'string' || outDir.trim().length === 0) throw new Error('--out-dir is required');
|
|
474
|
+
const dir = resolve(outDir);
|
|
475
|
+
await mkdir(dir, { recursive: true });
|
|
476
|
+
const files = {
|
|
477
|
+
'OPERATOR_EVIDENCE_STARTER.json': starter,
|
|
478
|
+
'hosted-refs.template.json': starter.hosted_required_refs,
|
|
479
|
+
'hosted-backend-live.template.json': starter.hosted_backend_live_evidence_template,
|
|
480
|
+
'infrastructure-readiness-manifest.template.json': starter.readiness_manifest,
|
|
481
|
+
'operator-acceptance-packet.template.json': starter.operator_acceptance_packet,
|
|
482
|
+
'owner-approval-refs.template.json': starter.owner_approval_refs_template,
|
|
483
|
+
'evidence-refs.template.json': starter.evidence_refs_template,
|
|
484
|
+
'commands.json': starter.commands,
|
|
485
|
+
'acceptance-fill-plan.json': starter.acceptance_fill_plan,
|
|
486
|
+
'hosted-ref-catalog.json': starter.hosted_ref_catalog,
|
|
487
|
+
'hosted-ref-workstreams.json': starter.hosted_ref_workstreams,
|
|
488
|
+
};
|
|
489
|
+
for (const [name, value] of Object.entries(files)) {
|
|
490
|
+
await writeFile(join(dir, name), `${JSON.stringify(value, null, 2)}\n`, 'utf8');
|
|
491
|
+
}
|
|
492
|
+
return {
|
|
493
|
+
ok: true,
|
|
494
|
+
schema: starter.schema,
|
|
495
|
+
out_dir: '<operator-evidence-starter-output>',
|
|
496
|
+
file_count: Object.keys(files).length,
|
|
497
|
+
generated_files: Object.keys(files),
|
|
498
|
+
hosted_ref_count: starter.counts.hosted_ref_count,
|
|
499
|
+
evidence_item_count: starter.counts.evidence_item_count,
|
|
500
|
+
status: starter.status,
|
|
501
|
+
};
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
function usage() {
|
|
505
|
+
return 'Usage: node scripts/build-operator-evidence-starter.mjs --out-dir <dir> [--domain enigmamemory.com] [--project-name enigma-memory] [--environment production] [--tenant enigma-memory]\n\nWrites public-safe starter JSON files for the operator evidence repository. It creates no cloud resources and does not mark hosted readiness complete.\n';
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
const invokedPath = process.argv[1] ? resolve(process.argv[1]) : '';
|
|
509
|
+
if (invokedPath === fileURLToPath(import.meta.url)) {
|
|
510
|
+
(async () => {
|
|
511
|
+
try {
|
|
512
|
+
const args = parseArgs();
|
|
513
|
+
if (args.help) {
|
|
514
|
+
process.stdout.write(usage());
|
|
515
|
+
return;
|
|
516
|
+
}
|
|
517
|
+
const starter = await buildOperatorEvidenceStarter({ args, generated_at: new Date().toISOString() });
|
|
518
|
+
if (args.outDir) process.stdout.write(`${JSON.stringify(await writeOperatorEvidenceStarter(starter, args.outDir), null, 2)}\n`);
|
|
519
|
+
else process.stdout.write(`${JSON.stringify(starter, null, 2)}\n`);
|
|
520
|
+
} catch (error) {
|
|
521
|
+
process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
|
|
522
|
+
process.exitCode = 1;
|
|
523
|
+
}
|
|
524
|
+
})();
|
|
525
|
+
}
|