sentinelayer-cli 0.4.4 → 0.6.2
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 +996 -998
- package/bin/create-sentinelayer.js +5 -5
- package/bin/sentinelayer-cli.js +4 -4
- package/bin/sl.js +5 -5
- package/package.json +63 -63
- package/src/agents/jules/config/definition.js +160 -209
- package/src/agents/jules/config/system-prompt.js +182 -175
- package/src/agents/jules/error-intake.js +51 -51
- package/src/agents/jules/fix-cycle.js +17 -377
- package/src/agents/jules/loop.js +450 -367
- package/src/agents/jules/pulse.js +10 -327
- package/src/agents/jules/stream.js +186 -186
- package/src/agents/jules/swarm/file-scanner.js +74 -74
- package/src/agents/jules/swarm/index.js +11 -11
- package/src/agents/jules/swarm/orchestrator.js +362 -362
- package/src/agents/jules/swarm/pattern-hunter.js +123 -123
- package/src/agents/jules/swarm/sub-agent.js +309 -308
- package/src/agents/jules/tools/aidenid-email.js +189 -0
- package/src/agents/jules/tools/auth-audit.js +1691 -557
- package/src/agents/jules/tools/dispatch.js +335 -327
- package/src/agents/jules/tools/file-edit.js +2 -180
- package/src/agents/jules/tools/file-read.js +2 -100
- package/src/agents/jules/tools/frontend-analyze.js +570 -570
- package/src/agents/jules/tools/glob.js +2 -168
- package/src/agents/jules/tools/grep.js +2 -228
- package/src/agents/jules/tools/index.js +29 -29
- package/src/agents/jules/tools/path-guards.js +2 -161
- package/src/agents/jules/tools/runtime-audit.js +507 -503
- package/src/agents/jules/tools/shell.js +2 -383
- package/src/agents/jules/tools/url-policy.js +100 -100
- package/src/agents/persona-visuals.js +61 -0
- package/src/agents/shared-tools/dispatch-core.js +315 -0
- package/src/agents/shared-tools/file-edit.js +180 -0
- package/src/agents/shared-tools/file-read.js +100 -0
- package/src/agents/shared-tools/glob.js +168 -0
- package/src/agents/shared-tools/grep.js +228 -0
- package/src/agents/shared-tools/index.js +46 -0
- package/src/agents/shared-tools/path-guards.js +161 -0
- package/src/agents/shared-tools/shell.js +383 -0
- package/src/ai/aidenid.js +1009 -972
- package/src/ai/client.js +553 -508
- package/src/ai/domain-target-store.js +268 -268
- package/src/ai/identity-store.js +270 -270
- package/src/ai/proxy.js +137 -0
- package/src/ai/site-store.js +145 -145
- package/src/audit/agents/architecture.js +180 -180
- package/src/audit/agents/compliance.js +179 -179
- package/src/audit/agents/documentation.js +165 -165
- package/src/audit/agents/performance.js +145 -145
- package/src/audit/agents/security.js +215 -215
- package/src/audit/agents/testing.js +172 -172
- package/src/audit/orchestrator.js +557 -557
- package/src/audit/package.js +204 -204
- package/src/audit/registry.js +284 -284
- package/src/audit/replay.js +103 -103
- package/src/auth/gate.js +371 -126
- package/src/auth/http.js +611 -270
- package/src/auth/service.js +1106 -891
- package/src/auth/session-store.js +813 -359
- package/src/cli.js +252 -252
- package/src/commands/ai/identity-lifecycle.js +1338 -1338
- package/src/commands/ai/provision-governance.js +1272 -1272
- package/src/commands/ai/shared.js +147 -147
- package/src/commands/ai.js +11 -11
- package/src/commands/apply.js +12 -12
- package/src/commands/audit.js +1166 -1166
- package/src/commands/auth.js +419 -375
- package/src/commands/chat.js +191 -191
- package/src/commands/config.js +184 -184
- package/src/commands/cost.js +311 -311
- package/src/commands/daemon/core.js +850 -850
- package/src/commands/daemon/extended.js +1048 -1048
- package/src/commands/daemon/shared.js +213 -213
- package/src/commands/daemon.js +11 -11
- package/src/commands/guide.js +174 -174
- package/src/commands/ingest.js +58 -58
- package/src/commands/init.js +55 -55
- package/src/commands/legacy-args.js +10 -10
- package/src/commands/mcp.js +461 -461
- package/src/commands/omargate.js +29 -21
- package/src/commands/persona.js +20 -20
- package/src/commands/plugin.js +260 -260
- package/src/commands/policy.js +132 -132
- package/src/commands/prompt.js +238 -238
- package/src/commands/review.js +704 -704
- package/src/commands/scan.js +872 -866
- package/src/commands/spec.js +716 -716
- package/src/commands/swarm.js +651 -651
- package/src/commands/telemetry.js +202 -202
- package/src/commands/watch.js +511 -510
- package/src/config/agent-dictionary.js +182 -182
- package/src/config/io.js +56 -56
- package/src/config/paths.js +18 -18
- package/src/config/schema.js +55 -55
- package/src/config/service.js +184 -184
- package/src/cost/budget.js +235 -235
- package/src/cost/history.js +188 -188
- package/src/cost/tracker.js +171 -171
- package/src/daemon/artifact-lineage.js +534 -534
- package/src/daemon/assignment-ledger.js +770 -770
- package/src/daemon/ast-parser-layer.js +258 -258
- package/src/daemon/budget-governor.js +633 -633
- package/src/daemon/callgraph-overlay.js +646 -646
- package/src/daemon/error-worker.js +626 -626
- package/src/daemon/fix-cycle.js +377 -0
- package/src/daemon/hybrid-mapper.js +929 -929
- package/src/daemon/jira-lifecycle.js +632 -632
- package/src/daemon/operator-control.js +657 -657
- package/src/daemon/pulse.js +327 -0
- package/src/daemon/reliability-lane.js +471 -471
- package/src/daemon/watchdog.js +971 -971
- package/src/guide/generator.js +316 -316
- package/src/ingest/engine.js +918 -918
- package/src/interactive/index.js +97 -95
- package/src/legacy-cli.js +2994 -2592
- package/src/mcp/registry.js +695 -695
- package/src/memory/blackboard.js +301 -301
- package/src/memory/retrieval.js +581 -581
- package/src/plugin/manifest.js +553 -553
- package/src/policy/packs.js +144 -144
- package/src/prompt/generator.js +118 -118
- package/src/review/ai-review.js +679 -669
- package/src/review/local-review.js +1305 -1295
- package/src/review/omargate-interactive.js +68 -0
- package/src/review/omargate-orchestrator.js +300 -0
- package/src/review/persona-prompts.js +296 -0
- package/src/review/replay.js +235 -235
- package/src/review/report.js +664 -664
- package/src/review/scan-modes.js +42 -0
- package/src/review/spec-binding.js +487 -487
- package/src/scaffold/generator.js +67 -67
- package/src/scaffold/templates.js +150 -150
- package/src/scan/generator.js +418 -418
- package/src/scan/gh-secrets.js +107 -107
- package/src/spec/generator.js +519 -519
- package/src/spec/regenerate.js +237 -237
- package/src/spec/templates.js +91 -91
- package/src/swarm/dashboard.js +247 -247
- package/src/swarm/factory.js +363 -363
- package/src/swarm/pentest.js +934 -934
- package/src/swarm/registry.js +419 -419
- package/src/swarm/report.js +158 -158
- package/src/swarm/runtime.js +576 -576
- package/src/swarm/scenario-dsl.js +272 -272
- package/src/telemetry/ledger.js +302 -302
- package/src/telemetry/session-tracker.js +234 -118
- package/src/telemetry/sync.js +203 -199
- package/src/ui/command-hints.js +13 -0
- package/src/ui/markdown.js +220 -220
|
@@ -1,268 +1,268 @@
|
|
|
1
|
-
import fsp from "node:fs/promises";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
|
|
4
|
-
const REGISTRY_SCHEMA_VERSION = "1.0.0";
|
|
5
|
-
|
|
6
|
-
function normalizeString(value) {
|
|
7
|
-
return String(value || "").trim();
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
function normalizeDomainRecord(record = {}) {
|
|
11
|
-
return {
|
|
12
|
-
domainId: normalizeString(record.domainId),
|
|
13
|
-
domainName: normalizeString(record.domainName) || null,
|
|
14
|
-
projectId: normalizeString(record.projectId) || null,
|
|
15
|
-
verificationStatus: normalizeString(record.verificationStatus) || "UNKNOWN",
|
|
16
|
-
freezeStatus: normalizeString(record.freezeStatus) || "UNKNOWN",
|
|
17
|
-
trustClass: normalizeString(record.trustClass) || null,
|
|
18
|
-
verificationMethod: normalizeString(record.verificationMethod) || null,
|
|
19
|
-
challengeValue: normalizeString(record.challengeValue) || null,
|
|
20
|
-
proofId: normalizeString(record.proofId) || null,
|
|
21
|
-
proofStatus: normalizeString(record.proofStatus) || null,
|
|
22
|
-
proofExpiresAt: normalizeString(record.proofExpiresAt) || null,
|
|
23
|
-
createdAt: normalizeString(record.createdAt) || new Date().toISOString(),
|
|
24
|
-
lastUpdatedAt: normalizeString(record.lastUpdatedAt) || new Date().toISOString(),
|
|
25
|
-
metadata: record.metadata && typeof record.metadata === "object" ? record.metadata : {},
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function normalizeTargetRecord(record = {}) {
|
|
30
|
-
return {
|
|
31
|
-
targetId: normalizeString(record.targetId),
|
|
32
|
-
host: normalizeString(record.host) || null,
|
|
33
|
-
domainId: normalizeString(record.domainId) || null,
|
|
34
|
-
projectId: normalizeString(record.projectId) || null,
|
|
35
|
-
verificationStatus: normalizeString(record.verificationStatus) || "UNKNOWN",
|
|
36
|
-
status: normalizeString(record.status) || "UNKNOWN",
|
|
37
|
-
freezeStatus: normalizeString(record.freezeStatus) || "UNKNOWN",
|
|
38
|
-
challengeValue: normalizeString(record.challengeValue) || null,
|
|
39
|
-
proofId: normalizeString(record.proofId) || null,
|
|
40
|
-
proofStatus: normalizeString(record.proofStatus) || null,
|
|
41
|
-
proofExpiresAt: normalizeString(record.proofExpiresAt) || null,
|
|
42
|
-
policy:
|
|
43
|
-
record.policy && typeof record.policy === "object"
|
|
44
|
-
? {
|
|
45
|
-
allowedPaths: Array.isArray(record.policy.allowedPaths) ? record.policy.allowedPaths : [],
|
|
46
|
-
allowedMethods: Array.isArray(record.policy.allowedMethods) ? record.policy.allowedMethods : [],
|
|
47
|
-
allowedScenarios: Array.isArray(record.policy.allowedScenarios)
|
|
48
|
-
? record.policy.allowedScenarios
|
|
49
|
-
: [],
|
|
50
|
-
maxRps: Number.isFinite(Number(record.policy.maxRps)) ? Number(record.policy.maxRps) : null,
|
|
51
|
-
maxConcurrency: Number.isFinite(Number(record.policy.maxConcurrency))
|
|
52
|
-
? Number(record.policy.maxConcurrency)
|
|
53
|
-
: null,
|
|
54
|
-
stopConditions:
|
|
55
|
-
record.policy.stopConditions && typeof record.policy.stopConditions === "object"
|
|
56
|
-
? record.policy.stopConditions
|
|
57
|
-
: {},
|
|
58
|
-
}
|
|
59
|
-
: {
|
|
60
|
-
allowedPaths: [],
|
|
61
|
-
allowedMethods: [],
|
|
62
|
-
allowedScenarios: [],
|
|
63
|
-
maxRps: null,
|
|
64
|
-
maxConcurrency: null,
|
|
65
|
-
stopConditions: {},
|
|
66
|
-
},
|
|
67
|
-
createdAt: normalizeString(record.createdAt) || new Date().toISOString(),
|
|
68
|
-
lastUpdatedAt: normalizeString(record.lastUpdatedAt) || new Date().toISOString(),
|
|
69
|
-
metadata: record.metadata && typeof record.metadata === "object" ? record.metadata : {},
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export function resolveDomainTargetRegistryPath({ outputRoot } = {}) {
|
|
74
|
-
const resolvedOutputRoot = path.resolve(String(outputRoot || "."));
|
|
75
|
-
return path.join(resolvedOutputRoot, "aidenid", "domain-target-registry.json");
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
async function loadRegistryInternal(filePath) {
|
|
79
|
-
try {
|
|
80
|
-
const raw = await fsp.readFile(filePath, "utf-8");
|
|
81
|
-
const parsed = JSON.parse(raw);
|
|
82
|
-
const domains = Array.isArray(parsed.domains)
|
|
83
|
-
? parsed.domains.map((item) => normalizeDomainRecord(item)).filter((item) => item.domainId)
|
|
84
|
-
: [];
|
|
85
|
-
const targets = Array.isArray(parsed.targets)
|
|
86
|
-
? parsed.targets.map((item) => normalizeTargetRecord(item)).filter((item) => item.targetId)
|
|
87
|
-
: [];
|
|
88
|
-
return {
|
|
89
|
-
schemaVersion: normalizeString(parsed.schemaVersion) || REGISTRY_SCHEMA_VERSION,
|
|
90
|
-
generatedAt: normalizeString(parsed.generatedAt) || new Date().toISOString(),
|
|
91
|
-
domains,
|
|
92
|
-
targets,
|
|
93
|
-
};
|
|
94
|
-
} catch (error) {
|
|
95
|
-
if (error && typeof error === "object" && error.code === "ENOENT") {
|
|
96
|
-
return {
|
|
97
|
-
schemaVersion: REGISTRY_SCHEMA_VERSION,
|
|
98
|
-
generatedAt: new Date().toISOString(),
|
|
99
|
-
domains: [],
|
|
100
|
-
targets: [],
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
throw error;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
async function writeRegistryInternal(filePath, registry = {}) {
|
|
108
|
-
const normalized = {
|
|
109
|
-
schemaVersion: REGISTRY_SCHEMA_VERSION,
|
|
110
|
-
generatedAt: new Date().toISOString(),
|
|
111
|
-
domains: Array.isArray(registry.domains) ? registry.domains.map(normalizeDomainRecord) : [],
|
|
112
|
-
targets: Array.isArray(registry.targets) ? registry.targets.map(normalizeTargetRecord) : [],
|
|
113
|
-
};
|
|
114
|
-
await fsp.mkdir(path.dirname(filePath), { recursive: true });
|
|
115
|
-
await fsp.writeFile(filePath, `${JSON.stringify(normalized, null, 2)}\n`, "utf-8");
|
|
116
|
-
return normalized;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
export async function listDomainTargetRecords({ outputRoot } = {}) {
|
|
120
|
-
const registryPath = resolveDomainTargetRegistryPath({ outputRoot });
|
|
121
|
-
const registry = await loadRegistryInternal(registryPath);
|
|
122
|
-
return {
|
|
123
|
-
registryPath,
|
|
124
|
-
domains: registry.domains,
|
|
125
|
-
targets: registry.targets,
|
|
126
|
-
};
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
export async function getDomainById({ outputRoot, domainId } = {}) {
|
|
130
|
-
const normalizedDomainId = normalizeString(domainId);
|
|
131
|
-
if (!normalizedDomainId) {
|
|
132
|
-
throw new Error("domainId is required.");
|
|
133
|
-
}
|
|
134
|
-
const { registryPath, domains } = await listDomainTargetRecords({ outputRoot });
|
|
135
|
-
const domain = domains.find((item) => item.domainId === normalizedDomainId) || null;
|
|
136
|
-
return {
|
|
137
|
-
registryPath,
|
|
138
|
-
domain,
|
|
139
|
-
};
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
export async function getTargetById({ outputRoot, targetId } = {}) {
|
|
143
|
-
const normalizedTargetId = normalizeString(targetId);
|
|
144
|
-
if (!normalizedTargetId) {
|
|
145
|
-
throw new Error("targetId is required.");
|
|
146
|
-
}
|
|
147
|
-
const { registryPath, targets } = await listDomainTargetRecords({ outputRoot });
|
|
148
|
-
const target = targets.find((item) => item.targetId === normalizedTargetId) || null;
|
|
149
|
-
return {
|
|
150
|
-
registryPath,
|
|
151
|
-
target,
|
|
152
|
-
};
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
export async function recordDomainProofResponse({
|
|
156
|
-
outputRoot,
|
|
157
|
-
domain = {},
|
|
158
|
-
proof = {},
|
|
159
|
-
context = {},
|
|
160
|
-
} = {}) {
|
|
161
|
-
const domainId = normalizeString(domain.id || context.domainId);
|
|
162
|
-
if (!domainId) {
|
|
163
|
-
throw new Error("Cannot record domain without domain.id.");
|
|
164
|
-
}
|
|
165
|
-
const registryPath = resolveDomainTargetRegistryPath({ outputRoot });
|
|
166
|
-
const registry = await loadRegistryInternal(registryPath);
|
|
167
|
-
const nowIso = new Date().toISOString();
|
|
168
|
-
const nextRecord = normalizeDomainRecord({
|
|
169
|
-
domainId,
|
|
170
|
-
domainName: domain.domainName,
|
|
171
|
-
projectId: domain.projectId || context.projectId,
|
|
172
|
-
verificationStatus: domain.verificationStatus,
|
|
173
|
-
freezeStatus: domain.freezeStatus,
|
|
174
|
-
trustClass: domain.trustClass,
|
|
175
|
-
verificationMethod: domain.verificationMethod,
|
|
176
|
-
challengeValue: proof.challengeValue || context.challengeValue,
|
|
177
|
-
proofId: proof.proofId,
|
|
178
|
-
proofStatus: proof.proofStatus,
|
|
179
|
-
proofExpiresAt: proof.proofExpiresAt,
|
|
180
|
-
createdAt: nowIso,
|
|
181
|
-
lastUpdatedAt: nowIso,
|
|
182
|
-
metadata: {
|
|
183
|
-
source: normalizeString(context.source) || "domain",
|
|
184
|
-
idempotencyKey: context.idempotencyKey || null,
|
|
185
|
-
},
|
|
186
|
-
});
|
|
187
|
-
|
|
188
|
-
const index = registry.domains.findIndex((item) => item.domainId === domainId);
|
|
189
|
-
if (index >= 0) {
|
|
190
|
-
const existing = registry.domains[index];
|
|
191
|
-
registry.domains[index] = normalizeDomainRecord({
|
|
192
|
-
...existing,
|
|
193
|
-
...nextRecord,
|
|
194
|
-
createdAt: existing.createdAt || nextRecord.createdAt,
|
|
195
|
-
metadata: {
|
|
196
|
-
...existing.metadata,
|
|
197
|
-
...nextRecord.metadata,
|
|
198
|
-
},
|
|
199
|
-
});
|
|
200
|
-
} else {
|
|
201
|
-
registry.domains.push(nextRecord);
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
const saved = await writeRegistryInternal(registryPath, registry);
|
|
205
|
-
const record = saved.domains.find((item) => item.domainId === domainId) || null;
|
|
206
|
-
return {
|
|
207
|
-
registryPath,
|
|
208
|
-
domain: record,
|
|
209
|
-
};
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
export async function recordTargetProofResponse({
|
|
213
|
-
outputRoot,
|
|
214
|
-
target = {},
|
|
215
|
-
proof = {},
|
|
216
|
-
context = {},
|
|
217
|
-
} = {}) {
|
|
218
|
-
const targetId = normalizeString(target.id || context.targetId);
|
|
219
|
-
if (!targetId) {
|
|
220
|
-
throw new Error("Cannot record target without target.id.");
|
|
221
|
-
}
|
|
222
|
-
const registryPath = resolveDomainTargetRegistryPath({ outputRoot });
|
|
223
|
-
const registry = await loadRegistryInternal(registryPath);
|
|
224
|
-
const nowIso = new Date().toISOString();
|
|
225
|
-
const nextRecord = normalizeTargetRecord({
|
|
226
|
-
targetId,
|
|
227
|
-
host: target.host,
|
|
228
|
-
domainId: target.domainId || context.domainId || null,
|
|
229
|
-
projectId: target.projectId || context.projectId || null,
|
|
230
|
-
verificationStatus: target.verificationStatus,
|
|
231
|
-
status: target.status,
|
|
232
|
-
freezeStatus: target.freezeStatus,
|
|
233
|
-
challengeValue: proof.challengeValue || context.challengeValue,
|
|
234
|
-
proofId: proof.proofId,
|
|
235
|
-
proofStatus: proof.proofStatus,
|
|
236
|
-
proofExpiresAt: proof.proofExpiresAt,
|
|
237
|
-
policy: target.policy || {},
|
|
238
|
-
createdAt: nowIso,
|
|
239
|
-
lastUpdatedAt: nowIso,
|
|
240
|
-
metadata: {
|
|
241
|
-
source: normalizeString(context.source) || "target",
|
|
242
|
-
idempotencyKey: context.idempotencyKey || null,
|
|
243
|
-
},
|
|
244
|
-
});
|
|
245
|
-
|
|
246
|
-
const index = registry.targets.findIndex((item) => item.targetId === targetId);
|
|
247
|
-
if (index >= 0) {
|
|
248
|
-
const existing = registry.targets[index];
|
|
249
|
-
registry.targets[index] = normalizeTargetRecord({
|
|
250
|
-
...existing,
|
|
251
|
-
...nextRecord,
|
|
252
|
-
createdAt: existing.createdAt || nextRecord.createdAt,
|
|
253
|
-
metadata: {
|
|
254
|
-
...existing.metadata,
|
|
255
|
-
...nextRecord.metadata,
|
|
256
|
-
},
|
|
257
|
-
});
|
|
258
|
-
} else {
|
|
259
|
-
registry.targets.push(nextRecord);
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
const saved = await writeRegistryInternal(registryPath, registry);
|
|
263
|
-
const record = saved.targets.find((item) => item.targetId === targetId) || null;
|
|
264
|
-
return {
|
|
265
|
-
registryPath,
|
|
266
|
-
target: record,
|
|
267
|
-
};
|
|
268
|
-
}
|
|
1
|
+
import fsp from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
|
|
4
|
+
const REGISTRY_SCHEMA_VERSION = "1.0.0";
|
|
5
|
+
|
|
6
|
+
function normalizeString(value) {
|
|
7
|
+
return String(value || "").trim();
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function normalizeDomainRecord(record = {}) {
|
|
11
|
+
return {
|
|
12
|
+
domainId: normalizeString(record.domainId),
|
|
13
|
+
domainName: normalizeString(record.domainName) || null,
|
|
14
|
+
projectId: normalizeString(record.projectId) || null,
|
|
15
|
+
verificationStatus: normalizeString(record.verificationStatus) || "UNKNOWN",
|
|
16
|
+
freezeStatus: normalizeString(record.freezeStatus) || "UNKNOWN",
|
|
17
|
+
trustClass: normalizeString(record.trustClass) || null,
|
|
18
|
+
verificationMethod: normalizeString(record.verificationMethod) || null,
|
|
19
|
+
challengeValue: normalizeString(record.challengeValue) || null,
|
|
20
|
+
proofId: normalizeString(record.proofId) || null,
|
|
21
|
+
proofStatus: normalizeString(record.proofStatus) || null,
|
|
22
|
+
proofExpiresAt: normalizeString(record.proofExpiresAt) || null,
|
|
23
|
+
createdAt: normalizeString(record.createdAt) || new Date().toISOString(),
|
|
24
|
+
lastUpdatedAt: normalizeString(record.lastUpdatedAt) || new Date().toISOString(),
|
|
25
|
+
metadata: record.metadata && typeof record.metadata === "object" ? record.metadata : {},
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function normalizeTargetRecord(record = {}) {
|
|
30
|
+
return {
|
|
31
|
+
targetId: normalizeString(record.targetId),
|
|
32
|
+
host: normalizeString(record.host) || null,
|
|
33
|
+
domainId: normalizeString(record.domainId) || null,
|
|
34
|
+
projectId: normalizeString(record.projectId) || null,
|
|
35
|
+
verificationStatus: normalizeString(record.verificationStatus) || "UNKNOWN",
|
|
36
|
+
status: normalizeString(record.status) || "UNKNOWN",
|
|
37
|
+
freezeStatus: normalizeString(record.freezeStatus) || "UNKNOWN",
|
|
38
|
+
challengeValue: normalizeString(record.challengeValue) || null,
|
|
39
|
+
proofId: normalizeString(record.proofId) || null,
|
|
40
|
+
proofStatus: normalizeString(record.proofStatus) || null,
|
|
41
|
+
proofExpiresAt: normalizeString(record.proofExpiresAt) || null,
|
|
42
|
+
policy:
|
|
43
|
+
record.policy && typeof record.policy === "object"
|
|
44
|
+
? {
|
|
45
|
+
allowedPaths: Array.isArray(record.policy.allowedPaths) ? record.policy.allowedPaths : [],
|
|
46
|
+
allowedMethods: Array.isArray(record.policy.allowedMethods) ? record.policy.allowedMethods : [],
|
|
47
|
+
allowedScenarios: Array.isArray(record.policy.allowedScenarios)
|
|
48
|
+
? record.policy.allowedScenarios
|
|
49
|
+
: [],
|
|
50
|
+
maxRps: Number.isFinite(Number(record.policy.maxRps)) ? Number(record.policy.maxRps) : null,
|
|
51
|
+
maxConcurrency: Number.isFinite(Number(record.policy.maxConcurrency))
|
|
52
|
+
? Number(record.policy.maxConcurrency)
|
|
53
|
+
: null,
|
|
54
|
+
stopConditions:
|
|
55
|
+
record.policy.stopConditions && typeof record.policy.stopConditions === "object"
|
|
56
|
+
? record.policy.stopConditions
|
|
57
|
+
: {},
|
|
58
|
+
}
|
|
59
|
+
: {
|
|
60
|
+
allowedPaths: [],
|
|
61
|
+
allowedMethods: [],
|
|
62
|
+
allowedScenarios: [],
|
|
63
|
+
maxRps: null,
|
|
64
|
+
maxConcurrency: null,
|
|
65
|
+
stopConditions: {},
|
|
66
|
+
},
|
|
67
|
+
createdAt: normalizeString(record.createdAt) || new Date().toISOString(),
|
|
68
|
+
lastUpdatedAt: normalizeString(record.lastUpdatedAt) || new Date().toISOString(),
|
|
69
|
+
metadata: record.metadata && typeof record.metadata === "object" ? record.metadata : {},
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function resolveDomainTargetRegistryPath({ outputRoot } = {}) {
|
|
74
|
+
const resolvedOutputRoot = path.resolve(String(outputRoot || "."));
|
|
75
|
+
return path.join(resolvedOutputRoot, "aidenid", "domain-target-registry.json");
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async function loadRegistryInternal(filePath) {
|
|
79
|
+
try {
|
|
80
|
+
const raw = await fsp.readFile(filePath, "utf-8");
|
|
81
|
+
const parsed = JSON.parse(raw);
|
|
82
|
+
const domains = Array.isArray(parsed.domains)
|
|
83
|
+
? parsed.domains.map((item) => normalizeDomainRecord(item)).filter((item) => item.domainId)
|
|
84
|
+
: [];
|
|
85
|
+
const targets = Array.isArray(parsed.targets)
|
|
86
|
+
? parsed.targets.map((item) => normalizeTargetRecord(item)).filter((item) => item.targetId)
|
|
87
|
+
: [];
|
|
88
|
+
return {
|
|
89
|
+
schemaVersion: normalizeString(parsed.schemaVersion) || REGISTRY_SCHEMA_VERSION,
|
|
90
|
+
generatedAt: normalizeString(parsed.generatedAt) || new Date().toISOString(),
|
|
91
|
+
domains,
|
|
92
|
+
targets,
|
|
93
|
+
};
|
|
94
|
+
} catch (error) {
|
|
95
|
+
if (error && typeof error === "object" && error.code === "ENOENT") {
|
|
96
|
+
return {
|
|
97
|
+
schemaVersion: REGISTRY_SCHEMA_VERSION,
|
|
98
|
+
generatedAt: new Date().toISOString(),
|
|
99
|
+
domains: [],
|
|
100
|
+
targets: [],
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
throw error;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
async function writeRegistryInternal(filePath, registry = {}) {
|
|
108
|
+
const normalized = {
|
|
109
|
+
schemaVersion: REGISTRY_SCHEMA_VERSION,
|
|
110
|
+
generatedAt: new Date().toISOString(),
|
|
111
|
+
domains: Array.isArray(registry.domains) ? registry.domains.map(normalizeDomainRecord) : [],
|
|
112
|
+
targets: Array.isArray(registry.targets) ? registry.targets.map(normalizeTargetRecord) : [],
|
|
113
|
+
};
|
|
114
|
+
await fsp.mkdir(path.dirname(filePath), { recursive: true });
|
|
115
|
+
await fsp.writeFile(filePath, `${JSON.stringify(normalized, null, 2)}\n`, "utf-8");
|
|
116
|
+
return normalized;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export async function listDomainTargetRecords({ outputRoot } = {}) {
|
|
120
|
+
const registryPath = resolveDomainTargetRegistryPath({ outputRoot });
|
|
121
|
+
const registry = await loadRegistryInternal(registryPath);
|
|
122
|
+
return {
|
|
123
|
+
registryPath,
|
|
124
|
+
domains: registry.domains,
|
|
125
|
+
targets: registry.targets,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export async function getDomainById({ outputRoot, domainId } = {}) {
|
|
130
|
+
const normalizedDomainId = normalizeString(domainId);
|
|
131
|
+
if (!normalizedDomainId) {
|
|
132
|
+
throw new Error("domainId is required.");
|
|
133
|
+
}
|
|
134
|
+
const { registryPath, domains } = await listDomainTargetRecords({ outputRoot });
|
|
135
|
+
const domain = domains.find((item) => item.domainId === normalizedDomainId) || null;
|
|
136
|
+
return {
|
|
137
|
+
registryPath,
|
|
138
|
+
domain,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export async function getTargetById({ outputRoot, targetId } = {}) {
|
|
143
|
+
const normalizedTargetId = normalizeString(targetId);
|
|
144
|
+
if (!normalizedTargetId) {
|
|
145
|
+
throw new Error("targetId is required.");
|
|
146
|
+
}
|
|
147
|
+
const { registryPath, targets } = await listDomainTargetRecords({ outputRoot });
|
|
148
|
+
const target = targets.find((item) => item.targetId === normalizedTargetId) || null;
|
|
149
|
+
return {
|
|
150
|
+
registryPath,
|
|
151
|
+
target,
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export async function recordDomainProofResponse({
|
|
156
|
+
outputRoot,
|
|
157
|
+
domain = {},
|
|
158
|
+
proof = {},
|
|
159
|
+
context = {},
|
|
160
|
+
} = {}) {
|
|
161
|
+
const domainId = normalizeString(domain.id || context.domainId);
|
|
162
|
+
if (!domainId) {
|
|
163
|
+
throw new Error("Cannot record domain without domain.id.");
|
|
164
|
+
}
|
|
165
|
+
const registryPath = resolveDomainTargetRegistryPath({ outputRoot });
|
|
166
|
+
const registry = await loadRegistryInternal(registryPath);
|
|
167
|
+
const nowIso = new Date().toISOString();
|
|
168
|
+
const nextRecord = normalizeDomainRecord({
|
|
169
|
+
domainId,
|
|
170
|
+
domainName: domain.domainName,
|
|
171
|
+
projectId: domain.projectId || context.projectId,
|
|
172
|
+
verificationStatus: domain.verificationStatus,
|
|
173
|
+
freezeStatus: domain.freezeStatus,
|
|
174
|
+
trustClass: domain.trustClass,
|
|
175
|
+
verificationMethod: domain.verificationMethod,
|
|
176
|
+
challengeValue: proof.challengeValue || context.challengeValue,
|
|
177
|
+
proofId: proof.proofId,
|
|
178
|
+
proofStatus: proof.proofStatus,
|
|
179
|
+
proofExpiresAt: proof.proofExpiresAt,
|
|
180
|
+
createdAt: nowIso,
|
|
181
|
+
lastUpdatedAt: nowIso,
|
|
182
|
+
metadata: {
|
|
183
|
+
source: normalizeString(context.source) || "domain",
|
|
184
|
+
idempotencyKey: context.idempotencyKey || null,
|
|
185
|
+
},
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
const index = registry.domains.findIndex((item) => item.domainId === domainId);
|
|
189
|
+
if (index >= 0) {
|
|
190
|
+
const existing = registry.domains[index];
|
|
191
|
+
registry.domains[index] = normalizeDomainRecord({
|
|
192
|
+
...existing,
|
|
193
|
+
...nextRecord,
|
|
194
|
+
createdAt: existing.createdAt || nextRecord.createdAt,
|
|
195
|
+
metadata: {
|
|
196
|
+
...existing.metadata,
|
|
197
|
+
...nextRecord.metadata,
|
|
198
|
+
},
|
|
199
|
+
});
|
|
200
|
+
} else {
|
|
201
|
+
registry.domains.push(nextRecord);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const saved = await writeRegistryInternal(registryPath, registry);
|
|
205
|
+
const record = saved.domains.find((item) => item.domainId === domainId) || null;
|
|
206
|
+
return {
|
|
207
|
+
registryPath,
|
|
208
|
+
domain: record,
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
export async function recordTargetProofResponse({
|
|
213
|
+
outputRoot,
|
|
214
|
+
target = {},
|
|
215
|
+
proof = {},
|
|
216
|
+
context = {},
|
|
217
|
+
} = {}) {
|
|
218
|
+
const targetId = normalizeString(target.id || context.targetId);
|
|
219
|
+
if (!targetId) {
|
|
220
|
+
throw new Error("Cannot record target without target.id.");
|
|
221
|
+
}
|
|
222
|
+
const registryPath = resolveDomainTargetRegistryPath({ outputRoot });
|
|
223
|
+
const registry = await loadRegistryInternal(registryPath);
|
|
224
|
+
const nowIso = new Date().toISOString();
|
|
225
|
+
const nextRecord = normalizeTargetRecord({
|
|
226
|
+
targetId,
|
|
227
|
+
host: target.host,
|
|
228
|
+
domainId: target.domainId || context.domainId || null,
|
|
229
|
+
projectId: target.projectId || context.projectId || null,
|
|
230
|
+
verificationStatus: target.verificationStatus,
|
|
231
|
+
status: target.status,
|
|
232
|
+
freezeStatus: target.freezeStatus,
|
|
233
|
+
challengeValue: proof.challengeValue || context.challengeValue,
|
|
234
|
+
proofId: proof.proofId,
|
|
235
|
+
proofStatus: proof.proofStatus,
|
|
236
|
+
proofExpiresAt: proof.proofExpiresAt,
|
|
237
|
+
policy: target.policy || {},
|
|
238
|
+
createdAt: nowIso,
|
|
239
|
+
lastUpdatedAt: nowIso,
|
|
240
|
+
metadata: {
|
|
241
|
+
source: normalizeString(context.source) || "target",
|
|
242
|
+
idempotencyKey: context.idempotencyKey || null,
|
|
243
|
+
},
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
const index = registry.targets.findIndex((item) => item.targetId === targetId);
|
|
247
|
+
if (index >= 0) {
|
|
248
|
+
const existing = registry.targets[index];
|
|
249
|
+
registry.targets[index] = normalizeTargetRecord({
|
|
250
|
+
...existing,
|
|
251
|
+
...nextRecord,
|
|
252
|
+
createdAt: existing.createdAt || nextRecord.createdAt,
|
|
253
|
+
metadata: {
|
|
254
|
+
...existing.metadata,
|
|
255
|
+
...nextRecord.metadata,
|
|
256
|
+
},
|
|
257
|
+
});
|
|
258
|
+
} else {
|
|
259
|
+
registry.targets.push(nextRecord);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
const saved = await writeRegistryInternal(registryPath, registry);
|
|
263
|
+
const record = saved.targets.find((item) => item.targetId === targetId) || null;
|
|
264
|
+
return {
|
|
265
|
+
registryPath,
|
|
266
|
+
target: record,
|
|
267
|
+
};
|
|
268
|
+
}
|