@aperant/framework 0.8.1 → 0.8.6
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/CHANGELOG.md +443 -1
- package/agents/apt-planner.md +39 -7
- package/dist/cli/commands/adr.mjs +1 -1
- package/dist/cli/commands/audit-branch-current.d.mts +25 -0
- package/dist/cli/commands/audit-branch-current.d.mts.map +1 -0
- package/dist/cli/commands/audit-branch-current.mjs +252 -0
- package/dist/cli/commands/audit-branch-current.mjs.map +1 -0
- package/dist/cli/commands/audit.d.mts.map +1 -1
- package/dist/cli/commands/audit.mjs +13 -2
- package/dist/cli/commands/audit.mjs.map +1 -1
- package/dist/cli/commands/check-version.d.mts.map +1 -1
- package/dist/cli/commands/check-version.mjs +19 -1
- package/dist/cli/commands/check-version.mjs.map +1 -1
- package/dist/cli/commands/context.mjs +3 -3
- package/dist/cli/commands/context.mjs.map +1 -1
- package/dist/cli/commands/coverage-check.d.mts.map +1 -1
- package/dist/cli/commands/coverage-check.mjs +74 -7
- package/dist/cli/commands/coverage-check.mjs.map +1 -1
- package/dist/cli/commands/detect-runtime.d.mts +6 -0
- package/dist/cli/commands/detect-runtime.d.mts.map +1 -0
- package/dist/cli/commands/detect-runtime.mjs +142 -0
- package/dist/cli/commands/detect-runtime.mjs.map +1 -0
- package/dist/cli/commands/driver-doctor.d.mts +29 -0
- package/dist/cli/commands/driver-doctor.d.mts.map +1 -0
- package/dist/cli/commands/driver-doctor.mjs +291 -0
- package/dist/cli/commands/driver-doctor.mjs.map +1 -0
- package/dist/cli/commands/gate.mjs +14 -0
- package/dist/cli/commands/gate.mjs.map +1 -1
- package/dist/cli/commands/init.d.mts.map +1 -1
- package/dist/cli/commands/init.mjs +9 -6
- package/dist/cli/commands/init.mjs.map +1 -1
- package/dist/cli/commands/install-from-source.d.mts +2 -0
- package/dist/cli/commands/install-from-source.d.mts.map +1 -0
- package/dist/cli/commands/install-from-source.mjs +2 -0
- package/dist/cli/commands/install-from-source.mjs.map +1 -0
- package/dist/cli/commands/modes.mjs +1 -1
- package/dist/cli/commands/route.d.mts.map +1 -1
- package/dist/cli/commands/route.mjs +38 -1
- package/dist/cli/commands/route.mjs.map +1 -1
- package/dist/cli/commands/triage.mjs +1 -1
- package/dist/cli/config/load.d.mts.map +1 -1
- package/dist/cli/config/load.mjs +9 -3
- package/dist/cli/config/load.mjs.map +1 -1
- package/dist/cli/coordination/auto-emit-artifact-ready.mjs +1 -1
- package/dist/cli/coordination/event-schema.d.mts.map +1 -1
- package/dist/cli/coordination/event-schema.mjs +18 -0
- package/dist/cli/coordination/event-schema.mjs.map +1 -1
- package/dist/cli/coverage-check/user-outcomes.d.mts +84 -0
- package/dist/cli/coverage-check/user-outcomes.d.mts.map +1 -0
- package/dist/cli/coverage-check/user-outcomes.mjs +265 -0
- package/dist/cli/coverage-check/user-outcomes.mjs.map +1 -0
- package/dist/cli/dispatch.d.mts.map +1 -1
- package/dist/cli/dispatch.mjs +18 -1
- package/dist/cli/dispatch.mjs.map +1 -1
- package/dist/cli/gate/context.d.mts +1 -0
- package/dist/cli/gate/context.d.mts.map +1 -1
- package/dist/cli/gate/context.mjs +14 -1
- package/dist/cli/gate/context.mjs.map +1 -1
- package/dist/cli/gate/gates/consistency-check.d.mts +1 -0
- package/dist/cli/gate/gates/consistency-check.d.mts.map +1 -1
- package/dist/cli/gate/gates/consistency-check.mjs +1 -0
- package/dist/cli/gate/gates/consistency-check.mjs.map +1 -1
- package/dist/cli/gate/gates/review-clean.d.mts +1 -0
- package/dist/cli/gate/gates/review-clean.d.mts.map +1 -1
- package/dist/cli/gate/gates/review-clean.mjs +1 -0
- package/dist/cli/gate/gates/review-clean.mjs.map +1 -1
- package/dist/cli/gate/gates/verify-approved.d.mts +1 -0
- package/dist/cli/gate/gates/verify-approved.d.mts.map +1 -1
- package/dist/cli/gate/gates/verify-approved.mjs +1 -0
- package/dist/cli/gate/gates/verify-approved.mjs.map +1 -1
- package/dist/cli/gate/registry.d.mts.map +1 -1
- package/dist/cli/gate/registry.mjs +9 -1
- package/dist/cli/gate/registry.mjs.map +1 -1
- package/dist/cli/host/detect.mjs +1 -1
- package/dist/cli/host/detect.mjs.map +1 -1
- package/dist/cli/install/find-workspace-framework-version.d.mts +16 -0
- package/dist/cli/install/find-workspace-framework-version.d.mts.map +1 -0
- package/dist/cli/install/find-workspace-framework-version.mjs +85 -0
- package/dist/cli/install/find-workspace-framework-version.mjs.map +1 -0
- package/dist/cli/install/install-from-source.d.mts +10 -0
- package/dist/cli/install/install-from-source.d.mts.map +1 -0
- package/dist/cli/install/install-from-source.mjs +271 -0
- package/dist/cli/install/install-from-source.mjs.map +1 -0
- package/dist/cli/install/install-kernel.d.mts.map +1 -1
- package/dist/cli/install/install-kernel.mjs +24 -0
- package/dist/cli/install/install-kernel.mjs.map +1 -1
- package/dist/cli/install/legacy-paths.d.mts +33 -11
- package/dist/cli/install/legacy-paths.d.mts.map +1 -1
- package/dist/cli/install/legacy-paths.mjs +163 -39
- package/dist/cli/install/legacy-paths.mjs.map +1 -1
- package/dist/cli/install/runtime-detect.mjs +1 -1
- package/dist/cli/install/runtime-detect.mjs.map +1 -1
- package/dist/cli/install/runtime-migrate.d.mts +34 -14
- package/dist/cli/install/runtime-migrate.d.mts.map +1 -1
- package/dist/cli/install/runtime-migrate.mjs +63 -30
- package/dist/cli/install/runtime-migrate.mjs.map +1 -1
- package/dist/cli/install/transforms/codex.d.mts.map +1 -1
- package/dist/cli/install/transforms/codex.mjs +28 -17
- package/dist/cli/install/transforms/codex.mjs.map +1 -1
- package/dist/cli/skill-author/contract.mjs +2 -2
- package/dist/cli/skill-author/contract.mjs.map +1 -1
- package/dist/cli/verify-proof/audit.d.mts +34 -0
- package/dist/cli/verify-proof/audit.d.mts.map +1 -0
- package/dist/cli/verify-proof/audit.mjs +53 -0
- package/dist/cli/verify-proof/audit.mjs.map +1 -0
- package/dist/cli/verify-proof/exec.d.mts +20 -0
- package/dist/cli/verify-proof/exec.d.mts.map +1 -0
- package/dist/cli/verify-proof/exec.mjs +74 -0
- package/dist/cli/verify-proof/exec.mjs.map +1 -0
- package/dist/cli/verify-proof/idl/index.d.mts +2 -0
- package/dist/cli/verify-proof/idl/index.d.mts.map +1 -0
- package/dist/cli/verify-proof/idl/index.mjs +13 -0
- package/dist/cli/verify-proof/idl/index.mjs.map +1 -0
- package/dist/cli/verify-proof/idl/types.d.ts +10 -0
- package/dist/cli/verify-proof/idl/types.d.ts.map +1 -0
- package/dist/cli/verify-proof/idl/types.js +10 -0
- package/dist/cli/verify-proof/idl/types.js.map +1 -0
- package/dist/cli/verify-proof/manifest-validator.d.mts +19 -0
- package/dist/cli/verify-proof/manifest-validator.d.mts.map +1 -0
- package/dist/cli/verify-proof/manifest-validator.mjs +182 -0
- package/dist/cli/verify-proof/manifest-validator.mjs.map +1 -0
- package/dist/cli/verify-proof/resolver.d.mts +105 -0
- package/dist/cli/verify-proof/resolver.d.mts.map +1 -0
- package/dist/cli/verify-proof/resolver.mjs +320 -0
- package/dist/cli/verify-proof/resolver.mjs.map +1 -0
- package/dist/cli/verify-proof/runtime-detect.d.mts +30 -0
- package/dist/cli/verify-proof/runtime-detect.d.mts.map +1 -0
- package/dist/cli/verify-proof/runtime-detect.mjs +209 -0
- package/dist/cli/verify-proof/runtime-detect.mjs.map +1 -0
- package/dist/cli/verify-proof/trust.d.mts +70 -0
- package/dist/cli/verify-proof/trust.d.mts.map +1 -0
- package/dist/cli/verify-proof/trust.mjs +174 -0
- package/dist/cli/verify-proof/trust.mjs.map +1 -0
- package/dist/driver-sdk/conformance.d.ts +41 -0
- package/dist/driver-sdk/conformance.d.ts.map +1 -0
- package/dist/driver-sdk/conformance.js +123 -0
- package/dist/driver-sdk/conformance.js.map +1 -0
- package/dist/driver-sdk/errors.d.ts +75 -0
- package/dist/driver-sdk/errors.d.ts.map +1 -0
- package/dist/driver-sdk/errors.js +80 -0
- package/dist/driver-sdk/errors.js.map +1 -0
- package/dist/driver-sdk/idl.d.ts +221 -0
- package/dist/driver-sdk/idl.d.ts.map +1 -0
- package/dist/driver-sdk/idl.js +140 -0
- package/dist/driver-sdk/idl.js.map +1 -0
- package/dist/driver-sdk/index.d.ts +28 -0
- package/dist/driver-sdk/index.d.ts.map +1 -0
- package/dist/driver-sdk/index.js +28 -0
- package/dist/driver-sdk/index.js.map +1 -0
- package/dist/driver-sdk/manifest.d.ts +93 -0
- package/dist/driver-sdk/manifest.d.ts.map +1 -0
- package/dist/driver-sdk/manifest.js +12 -0
- package/dist/driver-sdk/manifest.js.map +1 -0
- package/dist/driver-sdk/retry.d.ts +33 -0
- package/dist/driver-sdk/retry.d.ts.map +1 -0
- package/dist/driver-sdk/retry.js +50 -0
- package/dist/driver-sdk/retry.js.map +1 -0
- package/dist/plugin/.claude-plugin/plugin.json +4 -1
- package/dist/plugin/agents/apt-planner.md +39 -7
- package/dist/plugin/skills/apt/SKILL.md +75 -6
- package/dist/plugin/skills/apt-caveman/SKILL.md +64 -0
- package/dist/plugin/skills/apt-debug/SKILL.md +36 -4
- package/dist/plugin/skills/apt-debug/appendices/diagnose-discipline.md +2 -11
- package/dist/plugin/skills/apt-discuss/SKILL.md +4 -4
- package/dist/plugin/skills/apt-discuss/appendices/grill-discipline.md +2 -11
- package/dist/plugin/skills/apt-discuss/appendices/zoom-out-helper.md +0 -8
- package/dist/plugin/skills/apt-execute/SKILL.md +27 -4
- package/dist/plugin/skills/apt-execute/appendices/tdd-mode.md +2 -10
- package/dist/plugin/skills/apt-fan-out/SKILL.md +36 -1
- package/dist/plugin/skills/apt-handoff/SKILL.md +228 -0
- package/dist/plugin/skills/apt-improve/DEEPENING.md +0 -8
- package/dist/plugin/skills/apt-improve/INTERFACE-DESIGN.md +0 -8
- package/dist/plugin/skills/apt-improve/LANGUAGE.md +0 -8
- package/dist/plugin/skills/apt-improve/SKILL.md +4 -4
- package/dist/plugin/skills/apt-plan/SKILL.md +73 -5
- package/dist/plugin/skills/apt-plan/adapters/conductor.md +1 -1
- package/dist/plugin/skills/apt-pr-review/SKILL.md +1 -1
- package/dist/plugin/skills/apt-prototype/LOGIC.md +0 -8
- package/dist/plugin/skills/apt-prototype/SKILL.md +4 -4
- package/dist/plugin/skills/apt-prototype/UI.md +0 -8
- package/dist/plugin/skills/apt-quick/SKILL.md +31 -1
- package/dist/plugin/skills/apt-research/SKILL.md +526 -0
- package/dist/plugin/skills/apt-research/appendices/budget-loop.md +397 -0
- package/dist/plugin/skills/apt-research/appendices/claim-graph-schema.md +206 -0
- package/dist/plugin/skills/apt-research/appendices/domain-tools.md +236 -0
- package/dist/plugin/skills/apt-resume/SKILL.md +54 -31
- package/dist/plugin/skills/apt-run/SKILL.md +114 -16
- package/dist/plugin/skills/apt-setup/SKILL.md +97 -8
- package/dist/plugin/skills/apt-ship/SKILL.md +165 -9
- package/dist/plugin/skills/apt-spar/SKILL.md +84 -23
- package/dist/plugin/skills/apt-triage/AGENT-BRIEF.md +0 -8
- package/dist/plugin/skills/apt-triage/OUT-OF-SCOPE.md +0 -7
- package/dist/plugin/skills/apt-triage/SKILL.md +2 -2
- package/dist/plugin/skills/apt-update/SKILL.md +74 -17
- package/dist/plugin/skills/apt-verify-proof/SKILL.md +87 -1
- package/dist/plugin/skills/apt-zoom-out/SKILL.md +3 -3
- package/dist/schemas/quick-task.d.ts +17 -17
- package/dist/schemas/quick-task.d.ts.map +1 -1
- package/dist/schemas/quick-task.js +2 -2
- package/dist/schemas/quick-task.js.map +1 -1
- package/dist/types/config.d.ts +33 -0
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/state.d.ts +1 -1
- package/dist/types/state.d.ts.map +1 -1
- package/dist/types/task-record.d.ts +1 -1
- package/dist/types/task-record.d.ts.map +1 -1
- package/drivers/.gitkeep +0 -0
- package/drivers/api/README.md +40 -0
- package/drivers/api/driver.mjs +59 -0
- package/drivers/api/manifest.json +26 -0
- package/drivers/browser/README.md +105 -0
- package/drivers/browser/driver.mjs +134 -0
- package/drivers/browser/manifest.json +35 -0
- package/drivers/cli/README.md +44 -0
- package/drivers/cli/driver.mjs +62 -0
- package/drivers/cli/manifest.json +28 -0
- package/drivers/electron/README.md +64 -0
- package/drivers/electron/driver.mjs +87 -0
- package/drivers/electron/manifest.json +37 -0
- package/package.json +138 -133
- package/prompts/planner.md +1 -1
- package/prompts/spec_writer.md +1 -1
- package/skills/apt/SKILL.md +75 -6
- package/skills/apt-caveman/SKILL.md +64 -0
- package/skills/apt-debug/SKILL.md +36 -4
- package/skills/apt-debug/appendices/diagnose-discipline.md +2 -11
- package/skills/apt-discuss/SKILL.md +4 -4
- package/skills/apt-discuss/appendices/grill-discipline.md +2 -11
- package/skills/apt-discuss/appendices/zoom-out-helper.md +0 -8
- package/skills/apt-execute/SKILL.md +27 -4
- package/skills/apt-execute/appendices/tdd-mode.md +2 -10
- package/skills/apt-fan-out/SKILL.md +36 -1
- package/skills/apt-handoff/SKILL.md +228 -0
- package/skills/apt-improve/DEEPENING.md +0 -8
- package/skills/apt-improve/INTERFACE-DESIGN.md +0 -8
- package/skills/apt-improve/LANGUAGE.md +0 -8
- package/skills/apt-improve/SKILL.md +4 -4
- package/skills/apt-plan/SKILL.md +73 -5
- package/skills/apt-plan/adapters/conductor.md +1 -1
- package/skills/apt-planner.md +17 -1
- package/skills/apt-pr-review/SKILL.md +1 -1
- package/skills/apt-prototype/LOGIC.md +0 -8
- package/skills/apt-prototype/SKILL.md +4 -4
- package/skills/apt-prototype/UI.md +0 -8
- package/skills/apt-quick/SKILL.md +31 -1
- package/skills/apt-research/SKILL.md +526 -0
- package/skills/apt-research/appendices/budget-loop.md +397 -0
- package/skills/apt-research/appendices/claim-graph-schema.md +206 -0
- package/skills/apt-research/appendices/domain-tools.md +236 -0
- package/skills/apt-resume/SKILL.md +54 -31
- package/skills/apt-run/SKILL.md +114 -16
- package/skills/apt-setup/SKILL.md +97 -8
- package/skills/apt-ship/SKILL.md +165 -9
- package/skills/apt-spar/SKILL.md +84 -23
- package/skills/apt-triage/AGENT-BRIEF.md +0 -8
- package/skills/apt-triage/OUT-OF-SCOPE.md +0 -7
- package/skills/apt-triage/SKILL.md +2 -2
- package/skills/apt-update/SKILL.md +74 -17
- package/skills/apt-verify-proof/SKILL.md +87 -1
- package/skills/apt-zoom-out/SKILL.md +3 -3
- package/src/cli/commands/adr.mjs +1 -1
- package/src/cli/commands/audit-branch-current.mjs +250 -0
- package/src/cli/commands/audit.mjs +13 -2
- package/src/cli/commands/check-version.mjs +20 -1
- package/src/cli/commands/context.mjs +3 -3
- package/src/cli/commands/coverage-check.mjs +126 -44
- package/src/cli/commands/detect-runtime.mjs +143 -0
- package/src/cli/commands/driver-doctor.mjs +294 -0
- package/src/cli/commands/gate.mjs +15 -0
- package/src/cli/commands/init.mjs +9 -6
- package/src/cli/commands/install-from-source.mjs +1 -0
- package/src/cli/commands/modes.mjs +1 -1
- package/src/cli/commands/route.mjs +42 -1
- package/src/cli/commands/triage.mjs +1 -1
- package/src/cli/config/load.mjs +9 -3
- package/src/cli/coordination/auto-emit-artifact-ready.mjs +1 -1
- package/src/cli/coordination/event-schema.mjs +19 -0
- package/src/cli/coverage-check/user-outcomes.mjs +273 -0
- package/src/cli/dispatch.mjs +17 -1
- package/src/cli/gate/context.mjs +20 -1
- package/src/cli/gate/gates/consistency-check.mjs +1 -0
- package/src/cli/gate/gates/review-clean.mjs +1 -0
- package/src/cli/gate/gates/verify-approved.mjs +1 -0
- package/src/cli/gate/registry.mjs +11 -1
- package/src/cli/host/detect.mjs +1 -1
- package/src/cli/install/find-workspace-framework-version.mjs +88 -0
- package/src/cli/install/install-from-source.mjs +276 -0
- package/src/cli/install/install-kernel.mjs +24 -0
- package/src/cli/install/legacy-paths.mjs +164 -39
- package/src/cli/install/runtime-detect.mjs +1 -1
- package/src/cli/install/runtime-migrate.mjs +63 -30
- package/src/cli/install/transforms/codex.mjs +26 -17
- package/src/cli/skill-author/contract.mjs +2 -2
- package/src/cli/verify-proof/.gitkeep +0 -0
- package/src/cli/verify-proof/audit.mjs +55 -0
- package/src/cli/verify-proof/exec.mjs +74 -0
- package/src/cli/verify-proof/idl/index.mjs +23 -0
- package/src/cli/verify-proof/idl/types.ts +42 -0
- package/src/cli/verify-proof/manifest-schema.json +212 -0
- package/src/cli/verify-proof/manifest-validator.mjs +184 -0
- package/src/cli/verify-proof/resolver.mjs +330 -0
- package/src/cli/verify-proof/runtime-detect.mjs +211 -0
- package/src/cli/verify-proof/trust.mjs +187 -0
- package/templates/adr-format.md +0 -8
- package/templates/aperant-claude-md-appendix.md +1 -1
- package/templates/context-format.md +1 -9
- package/templates/proof-verification.md +51 -8
- package/workflows/verify-proof.md +130 -19
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* runtime-detect.mjs — pure project-shape capability detection.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from packages/core/src/prompts/prompt-loader.ts:572-595 so the
|
|
5
|
+
* framework CLI is self-contained (no @aperant/core dep). Same heuristics:
|
|
6
|
+
* read package.json's dependencies + devDependencies, return a capability
|
|
7
|
+
* record the resolver can score against.
|
|
8
|
+
*
|
|
9
|
+
* Pattern: pure data in → pure data out. No filesystem walking, no exec.
|
|
10
|
+
* Use loadRuntimeCapabilities(projectDir) for the cwd-rooted variant.
|
|
11
|
+
*
|
|
12
|
+
* v0.8.6 — `loadRuntimeCapabilities` now ALSO walks `apps/*` by default
|
|
13
|
+
* (configurable via the second arg `{monorepo_globs}`) and OR-merges
|
|
14
|
+
* each match's `package.json` capabilities with the root. The default
|
|
15
|
+
* `['apps/*']` matches the canonical Aperant monorepo layout; adopters
|
|
16
|
+
* whose monorepo lives elsewhere (e.g. `packages/apps/*`) pass a
|
|
17
|
+
* custom `monorepo_globs`. Setting `monorepo_globs: []` disables the
|
|
18
|
+
* walk entirely (root-only escape hatch).
|
|
19
|
+
*/
|
|
20
|
+
import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
|
|
21
|
+
import { join, resolve } from 'node:path';
|
|
22
|
+
/**
|
|
23
|
+
* @typedef {Object} RuntimeCapabilities
|
|
24
|
+
* @property {boolean} is_electron
|
|
25
|
+
* @property {boolean} is_tauri
|
|
26
|
+
* @property {boolean} is_nextjs
|
|
27
|
+
* @property {boolean} is_nuxt
|
|
28
|
+
* @property {boolean} is_web_frontend
|
|
29
|
+
* @property {boolean} is_expo
|
|
30
|
+
* @property {boolean} is_react_native
|
|
31
|
+
* @property {boolean} has_node
|
|
32
|
+
*/
|
|
33
|
+
/** A capability record with every flag defaulted to false. */
|
|
34
|
+
function emptyCapabilities() {
|
|
35
|
+
return {
|
|
36
|
+
is_electron: false,
|
|
37
|
+
is_tauri: false,
|
|
38
|
+
is_nextjs: false,
|
|
39
|
+
is_nuxt: false,
|
|
40
|
+
is_web_frontend: false,
|
|
41
|
+
is_expo: false,
|
|
42
|
+
is_react_native: false,
|
|
43
|
+
has_node: false,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Detect runtime capabilities from a parsed package.json object.
|
|
48
|
+
*
|
|
49
|
+
* @param {Record<string, unknown> | null} packageJson
|
|
50
|
+
* @returns {RuntimeCapabilities}
|
|
51
|
+
*/
|
|
52
|
+
export function detectFromPackageJson(packageJson) {
|
|
53
|
+
const capabilities = emptyCapabilities();
|
|
54
|
+
if (packageJson === null || typeof packageJson !== 'object')
|
|
55
|
+
return capabilities;
|
|
56
|
+
const allDeps = {
|
|
57
|
+
...(packageJson.dependencies ?? {}) /** @type {Record<string,string>} */,
|
|
58
|
+
...(packageJson.devDependencies ?? {}) /** @type {Record<string,string>} */,
|
|
59
|
+
};
|
|
60
|
+
const deps = new Set(Object.keys(allDeps).map((k) => k.toLowerCase()));
|
|
61
|
+
if (deps.has('electron') || [...deps].some((d) => d.startsWith('@electron'))) {
|
|
62
|
+
capabilities.is_electron = true;
|
|
63
|
+
}
|
|
64
|
+
if (deps.has('@tauri-apps/api') || deps.has('tauri')) {
|
|
65
|
+
capabilities.is_tauri = true;
|
|
66
|
+
}
|
|
67
|
+
if (deps.has('expo'))
|
|
68
|
+
capabilities.is_expo = true;
|
|
69
|
+
if (deps.has('react-native'))
|
|
70
|
+
capabilities.is_react_native = true;
|
|
71
|
+
// Web frontends — react/vue/svelte/angular/solid → frontend. BUT: an
|
|
72
|
+
// Electron app commonly bundles React as its renderer; in that case the
|
|
73
|
+
// runtime is "electron", not "web_frontend". Electron + react-native +
|
|
74
|
+
// expo + tauri all win over the web flag.
|
|
75
|
+
const isNativeContainer = capabilities.is_electron ||
|
|
76
|
+
capabilities.is_tauri ||
|
|
77
|
+
capabilities.is_react_native ||
|
|
78
|
+
capabilities.is_expo;
|
|
79
|
+
const webFrameworks = ['react', 'vue', 'svelte', 'angular', 'solid'];
|
|
80
|
+
if (!isNativeContainer && webFrameworks.some((f) => deps.has(f))) {
|
|
81
|
+
capabilities.is_web_frontend = true;
|
|
82
|
+
}
|
|
83
|
+
if (deps.has('next')) {
|
|
84
|
+
capabilities.is_nextjs = true;
|
|
85
|
+
capabilities.is_web_frontend = true;
|
|
86
|
+
}
|
|
87
|
+
if (deps.has('nuxt')) {
|
|
88
|
+
capabilities.is_nuxt = true;
|
|
89
|
+
capabilities.is_web_frontend = true;
|
|
90
|
+
}
|
|
91
|
+
if (deps.has('vite') && !isNativeContainer) {
|
|
92
|
+
capabilities.is_web_frontend = true;
|
|
93
|
+
}
|
|
94
|
+
// Node-ish? Anything with a package.json + an entry point counts.
|
|
95
|
+
if (typeof packageJson.main === 'string' || typeof packageJson.module === 'string') {
|
|
96
|
+
capabilities.has_node = true;
|
|
97
|
+
}
|
|
98
|
+
if (!capabilities.has_node && packageJson.scripts && typeof packageJson.scripts === 'object') {
|
|
99
|
+
capabilities.has_node = true;
|
|
100
|
+
}
|
|
101
|
+
return capabilities;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Load and detect capabilities from a project directory's package.json.
|
|
105
|
+
* v0.8.6 — also walks `monorepo_globs` (default `['apps/*']`) and
|
|
106
|
+
* OR-merges each match's capabilities with the root.
|
|
107
|
+
*
|
|
108
|
+
* @param {string} projectDir
|
|
109
|
+
* @param {{monorepo_globs?: string[]}} [opts]
|
|
110
|
+
* @returns {RuntimeCapabilities}
|
|
111
|
+
*/
|
|
112
|
+
export function loadRuntimeCapabilities(projectDir, opts) {
|
|
113
|
+
const root = resolve(projectDir);
|
|
114
|
+
const rootPkgPath = join(root, 'package.json');
|
|
115
|
+
let rootCaps = emptyCapabilities();
|
|
116
|
+
if (existsSync(rootPkgPath)) {
|
|
117
|
+
try {
|
|
118
|
+
rootCaps = detectFromPackageJson(JSON.parse(readFileSync(rootPkgPath, 'utf-8')));
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
/* fall through with empty caps */
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
// Default to the canonical Aperant monorepo layout. Passing `[]`
|
|
125
|
+
// disables the walk entirely (root-only escape hatch per spec ID-05).
|
|
126
|
+
const globs = opts && Array.isArray(opts.monorepo_globs) ? opts.monorepo_globs : ['apps/*'];
|
|
127
|
+
if (globs.length === 0)
|
|
128
|
+
return rootCaps;
|
|
129
|
+
let merged = rootCaps;
|
|
130
|
+
for (const glob of globs) {
|
|
131
|
+
const matches = expandSimpleGlob(root, glob);
|
|
132
|
+
for (const dir of matches) {
|
|
133
|
+
const childPkgPath = join(dir, 'package.json');
|
|
134
|
+
if (!existsSync(childPkgPath))
|
|
135
|
+
continue;
|
|
136
|
+
try {
|
|
137
|
+
const childCaps = detectFromPackageJson(JSON.parse(readFileSync(childPkgPath, 'utf-8')));
|
|
138
|
+
merged = orMergeCapabilities(merged, childCaps);
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
/* skip malformed package.json */
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return merged;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Expand a simple `prefix/*` glob against the root. Supports ONLY the
|
|
149
|
+
* `<dir>/*` shape (matches each direct subdirectory of `<dir>`). Other
|
|
150
|
+
* glob syntax is intentionally rejected — v1 keeps the dep surface
|
|
151
|
+
* small. Fails closed on malformed patterns (returns []).
|
|
152
|
+
*
|
|
153
|
+
* @param {string} root
|
|
154
|
+
* @param {string} glob
|
|
155
|
+
* @returns {string[]}
|
|
156
|
+
*/
|
|
157
|
+
function expandSimpleGlob(root, glob) {
|
|
158
|
+
if (typeof glob !== 'string' || !glob.endsWith('/*'))
|
|
159
|
+
return [];
|
|
160
|
+
const prefix = glob.slice(0, -2);
|
|
161
|
+
if (prefix.length === 0 || prefix.includes('*'))
|
|
162
|
+
return [];
|
|
163
|
+
const dir = join(root, prefix);
|
|
164
|
+
if (!existsSync(dir))
|
|
165
|
+
return [];
|
|
166
|
+
let entries;
|
|
167
|
+
try {
|
|
168
|
+
entries = readdirSync(dir);
|
|
169
|
+
}
|
|
170
|
+
catch {
|
|
171
|
+
return [];
|
|
172
|
+
}
|
|
173
|
+
const matches = [];
|
|
174
|
+
for (const name of entries) {
|
|
175
|
+
const sub = join(dir, name);
|
|
176
|
+
try {
|
|
177
|
+
if (statSync(sub).isDirectory())
|
|
178
|
+
matches.push(sub);
|
|
179
|
+
}
|
|
180
|
+
catch {
|
|
181
|
+
/* skip unreadable entries */
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return matches;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Boolean OR-merge of two capability records. Any flag true in either
|
|
188
|
+
* input is true in the output. The "Electron wins over web" rule from
|
|
189
|
+
* `detectFromPackageJson` is preserved when this is called repeatedly —
|
|
190
|
+
* each child's flags are honest about that child's own shape, and the
|
|
191
|
+
* OR-merge just unions them.
|
|
192
|
+
*
|
|
193
|
+
* @param {RuntimeCapabilities} a
|
|
194
|
+
* @param {RuntimeCapabilities} b
|
|
195
|
+
* @returns {RuntimeCapabilities}
|
|
196
|
+
*/
|
|
197
|
+
function orMergeCapabilities(a, b) {
|
|
198
|
+
return {
|
|
199
|
+
is_electron: a.is_electron || b.is_electron,
|
|
200
|
+
is_tauri: a.is_tauri || b.is_tauri,
|
|
201
|
+
is_nextjs: a.is_nextjs || b.is_nextjs,
|
|
202
|
+
is_nuxt: a.is_nuxt || b.is_nuxt,
|
|
203
|
+
is_web_frontend: a.is_web_frontend || b.is_web_frontend,
|
|
204
|
+
is_expo: a.is_expo || b.is_expo,
|
|
205
|
+
is_react_native: a.is_react_native || b.is_react_native,
|
|
206
|
+
has_node: a.has_node || b.has_node,
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
//# sourceMappingURL=runtime-detect.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-detect.mjs","sourceRoot":"","sources":["../../../src/cli/verify-proof/runtime-detect.mjs"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compute a stable manifest hash for TOFU + audit lines.
|
|
3
|
+
* @param {DriverManifest} manifest
|
|
4
|
+
* @returns {string}
|
|
5
|
+
*/
|
|
6
|
+
export function manifestSha256(manifest: DriverManifest): string;
|
|
7
|
+
/**
|
|
8
|
+
* Read the TOFU lock file. Returns an empty object if missing or malformed.
|
|
9
|
+
* @param {string} projectDir
|
|
10
|
+
* @returns {Record<string, {manifest_sha256: string, artifact_digest?: string, approved_at: string, trust_tier: string}>}
|
|
11
|
+
*/
|
|
12
|
+
export function readTofuLock(projectDir: string): Record<string, {
|
|
13
|
+
manifest_sha256: string;
|
|
14
|
+
artifact_digest?: string;
|
|
15
|
+
approved_at: string;
|
|
16
|
+
trust_tier: string;
|
|
17
|
+
}>;
|
|
18
|
+
/**
|
|
19
|
+
* Persist a TOFU lock file (atomic-ish: write + rename not used since we
|
|
20
|
+
* append-only to a tiny JSON; conflicting writes from parallel agents
|
|
21
|
+
* would clobber an entry but `.aperant/driver-tofu.json` is per-project,
|
|
22
|
+
* not per-agent).
|
|
23
|
+
*
|
|
24
|
+
* @param {string} projectDir
|
|
25
|
+
* @param {Record<string, unknown>} tofu
|
|
26
|
+
*/
|
|
27
|
+
export function writeTofuLock(projectDir: string, tofu: Record<string, unknown>): void;
|
|
28
|
+
/**
|
|
29
|
+
* Build the canonical TOFU key for a (driver, version) pair. The hash is
|
|
30
|
+
* NOT part of the key — the value's manifest_sha256 + artifact_digest
|
|
31
|
+
* detect drift.
|
|
32
|
+
* @param {string} driverId
|
|
33
|
+
* @param {string} version
|
|
34
|
+
* @returns {string}
|
|
35
|
+
*/
|
|
36
|
+
export function tofuKey(driverId: string, version: string): string;
|
|
37
|
+
/**
|
|
38
|
+
* Read the project's policy file. Returns the default policy if missing.
|
|
39
|
+
* @param {string} projectDir
|
|
40
|
+
* @returns {{mode: 'first_party_only' | 'allowlist', allowed: string[], denied: string[]}}
|
|
41
|
+
*/
|
|
42
|
+
export function readPolicy(projectDir: string): {
|
|
43
|
+
mode: "first_party_only" | "allowlist";
|
|
44
|
+
allowed: string[];
|
|
45
|
+
denied: string[];
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Decide whether a driver invocation is allowed.
|
|
49
|
+
*
|
|
50
|
+
* @param {DriverManifest} manifest
|
|
51
|
+
* @param {ReturnType<typeof readTofuLock>} tofu
|
|
52
|
+
* @param {ReturnType<typeof readPolicy>} policy
|
|
53
|
+
* @returns {{decision: 'allow' | 'deny' | 'requires_approval', reason: string, expected_manifest_sha256?: string}}
|
|
54
|
+
*/
|
|
55
|
+
export function decide(manifest: DriverManifest, tofu: ReturnType<typeof readTofuLock>, policy: ReturnType<typeof readPolicy>): {
|
|
56
|
+
decision: "allow" | "deny" | "requires_approval";
|
|
57
|
+
reason: string;
|
|
58
|
+
expected_manifest_sha256?: string;
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* Persist a one-time approval for a (driver, version) pair into the TOFU
|
|
62
|
+
* lock. The caller is responsible for actually prompting the user; this
|
|
63
|
+
* function just writes the entry.
|
|
64
|
+
*
|
|
65
|
+
* @param {string} projectDir
|
|
66
|
+
* @param {DriverManifest} manifest
|
|
67
|
+
*/
|
|
68
|
+
export function recordApproval(projectDir: string, manifest: DriverManifest): void;
|
|
69
|
+
export type DriverManifest = import("@aperant/framework/driver-sdk").DriverManifest;
|
|
70
|
+
//# sourceMappingURL=trust.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trust.d.mts","sourceRoot":"","sources":["../../../src/cli/verify-proof/trust.mjs"],"names":[],"mappings":"AA+BA;;;;GAIG;AACH,yCAHW,cAAc,GACZ,MAAM,CAKlB;AAED;;;;GAIG;AACH,yCAHW,MAAM,GACJ,MAAM,CAAC,MAAM,EAAE;IAAC,eAAe,EAAE,MAAM,CAAC;IAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAC,CAAC,CAUxH;AAED;;;;;;;;GAQG;AACH,0CAHW,MAAM,QACN,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,QAMjC;AAED;;;;;;;GAOG;AACH,kCAJW,MAAM,WACN,MAAM,GACJ,MAAM,CAIlB;AAED;;;;GAIG;AACH,uCAHW,MAAM,GACJ;IAAC,IAAI,EAAE,kBAAkB,GAAG,WAAW,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAC,CAgBzF;AAED;;;;;;;GAOG;AACH,iCALW,cAAc,QACd,UAAU,CAAC,OAAO,YAAY,CAAC,UAC/B,UAAU,CAAC,OAAO,UAAU,CAAC,GAC3B;IAAC,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,mBAAmB,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,wBAAwB,CAAC,EAAE,MAAM,CAAA;CAAC,CAwDjH;AAED;;;;;;;GAOG;AACH,2CAHW,MAAM,YACN,cAAc,QAYxB;6BAjKY,OAAO,+BAA+B,EAAE,cAAc"}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* trust.mjs — driver trust enforcement (TOFU lock + policy file + decision).
|
|
3
|
+
*
|
|
4
|
+
* Implements ID-03:
|
|
5
|
+
* - 4 trust tiers: first_party_signed (default-allow), community_verified,
|
|
6
|
+
* community_unverified, local_unverified.
|
|
7
|
+
* - Default policy: only first_party_signed auto-runs.
|
|
8
|
+
* - Non-first-party drivers require one-time user approval; approval is
|
|
9
|
+
* bound to a TOFU lock at .aperant/driver-tofu.json keyed by
|
|
10
|
+
* {driver_id, version, manifest_sha256, artifact_digest}. Any drift
|
|
11
|
+
* re-prompts.
|
|
12
|
+
*
|
|
13
|
+
* The audit log (audit.mjs) writes one line per decision (allow/deny).
|
|
14
|
+
* The execution layer (exec.mjs) enforces structured-only local_command.
|
|
15
|
+
*
|
|
16
|
+
* This module is decision-only: it does NOT prompt the user. The caller
|
|
17
|
+
* (workflow runner / apt-tools driver doctor) decides whether to invoke
|
|
18
|
+
* the prompt UX, then calls recordApproval() to persist the TOFU entry.
|
|
19
|
+
*/
|
|
20
|
+
import { createHash } from 'node:crypto';
|
|
21
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
22
|
+
import { dirname, join, resolve } from 'node:path';
|
|
23
|
+
/**
|
|
24
|
+
* @typedef {import('@aperant/framework/driver-sdk').DriverManifest} DriverManifest
|
|
25
|
+
*/
|
|
26
|
+
const TOFU_PATH = '.aperant/driver-tofu.json';
|
|
27
|
+
const POLICY_PATH = '.aperant/policy.json';
|
|
28
|
+
/**
|
|
29
|
+
* Compute a stable manifest hash for TOFU + audit lines.
|
|
30
|
+
* @param {DriverManifest} manifest
|
|
31
|
+
* @returns {string}
|
|
32
|
+
*/
|
|
33
|
+
export function manifestSha256(manifest) {
|
|
34
|
+
const stable = JSON.stringify(manifest, Object.keys(manifest).sort());
|
|
35
|
+
return createHash('sha256').update(stable).digest('hex');
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Read the TOFU lock file. Returns an empty object if missing or malformed.
|
|
39
|
+
* @param {string} projectDir
|
|
40
|
+
* @returns {Record<string, {manifest_sha256: string, artifact_digest?: string, approved_at: string, trust_tier: string}>}
|
|
41
|
+
*/
|
|
42
|
+
export function readTofuLock(projectDir) {
|
|
43
|
+
const path = join(resolve(projectDir), TOFU_PATH);
|
|
44
|
+
if (!existsSync(path))
|
|
45
|
+
return {};
|
|
46
|
+
try {
|
|
47
|
+
return JSON.parse(readFileSync(path, 'utf-8'));
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return {};
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Persist a TOFU lock file (atomic-ish: write + rename not used since we
|
|
55
|
+
* append-only to a tiny JSON; conflicting writes from parallel agents
|
|
56
|
+
* would clobber an entry but `.aperant/driver-tofu.json` is per-project,
|
|
57
|
+
* not per-agent).
|
|
58
|
+
*
|
|
59
|
+
* @param {string} projectDir
|
|
60
|
+
* @param {Record<string, unknown>} tofu
|
|
61
|
+
*/
|
|
62
|
+
export function writeTofuLock(projectDir, tofu) {
|
|
63
|
+
const path = join(resolve(projectDir), TOFU_PATH);
|
|
64
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
65
|
+
writeFileSync(path, JSON.stringify(tofu, null, 2) + '\n', 'utf-8');
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Build the canonical TOFU key for a (driver, version) pair. The hash is
|
|
69
|
+
* NOT part of the key — the value's manifest_sha256 + artifact_digest
|
|
70
|
+
* detect drift.
|
|
71
|
+
* @param {string} driverId
|
|
72
|
+
* @param {string} version
|
|
73
|
+
* @returns {string}
|
|
74
|
+
*/
|
|
75
|
+
export function tofuKey(driverId, version) {
|
|
76
|
+
return `${driverId}@${version}`;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Read the project's policy file. Returns the default policy if missing.
|
|
80
|
+
* @param {string} projectDir
|
|
81
|
+
* @returns {{mode: 'first_party_only' | 'allowlist', allowed: string[], denied: string[]}}
|
|
82
|
+
*/
|
|
83
|
+
export function readPolicy(projectDir) {
|
|
84
|
+
const path = join(resolve(projectDir), POLICY_PATH);
|
|
85
|
+
const defaults = { mode: 'first_party_only', allowed: [], denied: [] };
|
|
86
|
+
if (!existsSync(path))
|
|
87
|
+
return defaults;
|
|
88
|
+
try {
|
|
89
|
+
const parsed = JSON.parse(readFileSync(path, 'utf-8'));
|
|
90
|
+
return {
|
|
91
|
+
mode: parsed.mode === 'allowlist' ? 'allowlist' : 'first_party_only',
|
|
92
|
+
allowed: Array.isArray(parsed.allowed) ? parsed.allowed : [],
|
|
93
|
+
denied: Array.isArray(parsed.denied) ? parsed.denied : [],
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
return defaults;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Decide whether a driver invocation is allowed.
|
|
102
|
+
*
|
|
103
|
+
* @param {DriverManifest} manifest
|
|
104
|
+
* @param {ReturnType<typeof readTofuLock>} tofu
|
|
105
|
+
* @param {ReturnType<typeof readPolicy>} policy
|
|
106
|
+
* @returns {{decision: 'allow' | 'deny' | 'requires_approval', reason: string, expected_manifest_sha256?: string}}
|
|
107
|
+
*/
|
|
108
|
+
export function decide(manifest, tofu, policy) {
|
|
109
|
+
const tier = manifest.trust?.tier;
|
|
110
|
+
const driverId = manifest.driverId;
|
|
111
|
+
const version = manifest.version;
|
|
112
|
+
// Policy denylist always wins.
|
|
113
|
+
if (policy.denied.includes(driverId)) {
|
|
114
|
+
return { decision: 'deny', reason: `policy denies driver ${driverId}` };
|
|
115
|
+
}
|
|
116
|
+
// first_party_signed: default-allow under either policy mode (unless
|
|
117
|
+
// explicitly denied above).
|
|
118
|
+
if (tier === 'first_party_signed') {
|
|
119
|
+
return { decision: 'allow', reason: 'first_party_signed driver — default allow' };
|
|
120
|
+
}
|
|
121
|
+
// first_party_only mode blocks every other tier.
|
|
122
|
+
if (policy.mode === 'first_party_only') {
|
|
123
|
+
return {
|
|
124
|
+
decision: 'deny',
|
|
125
|
+
reason: `policy.mode=first_party_only blocks ${tier} driver`,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
// allowlist mode: require explicit allow entry AND a valid TOFU lock.
|
|
129
|
+
if (!policy.allowed.includes(driverId)) {
|
|
130
|
+
return {
|
|
131
|
+
decision: 'deny',
|
|
132
|
+
reason: `policy.mode=allowlist but ${driverId} not in allowed[]`,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
// Check TOFU lock.
|
|
136
|
+
const key = tofuKey(driverId, version);
|
|
137
|
+
const entry = tofu[key];
|
|
138
|
+
const currentHash = manifestSha256(manifest);
|
|
139
|
+
if (!entry) {
|
|
140
|
+
return {
|
|
141
|
+
decision: 'requires_approval',
|
|
142
|
+
reason: `no TOFU entry for ${key} — first run requires approval`,
|
|
143
|
+
expected_manifest_sha256: currentHash,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
if (entry.manifest_sha256 !== currentHash) {
|
|
147
|
+
return {
|
|
148
|
+
decision: 'requires_approval',
|
|
149
|
+
reason: `TOFU manifest_sha256 drift for ${key} — driver changed since approval, re-prompt required`,
|
|
150
|
+
expected_manifest_sha256: currentHash,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
return { decision: 'allow', reason: `TOFU entry valid for ${key}` };
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Persist a one-time approval for a (driver, version) pair into the TOFU
|
|
157
|
+
* lock. The caller is responsible for actually prompting the user; this
|
|
158
|
+
* function just writes the entry.
|
|
159
|
+
*
|
|
160
|
+
* @param {string} projectDir
|
|
161
|
+
* @param {DriverManifest} manifest
|
|
162
|
+
*/
|
|
163
|
+
export function recordApproval(projectDir, manifest) {
|
|
164
|
+
const tofu = readTofuLock(projectDir);
|
|
165
|
+
const key = tofuKey(manifest.driverId, manifest.version);
|
|
166
|
+
tofu[key] = {
|
|
167
|
+
manifest_sha256: manifestSha256(manifest),
|
|
168
|
+
artifact_digest: manifest.trust?.integrity?.artifact_digest,
|
|
169
|
+
approved_at: new Date().toISOString(),
|
|
170
|
+
trust_tier: manifest.trust?.tier,
|
|
171
|
+
};
|
|
172
|
+
writeTofuLock(projectDir, tofu);
|
|
173
|
+
}
|
|
174
|
+
//# sourceMappingURL=trust.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trust.mjs","sourceRoot":"","sources":["../../../src/cli/verify-proof/trust.mjs"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* conformance.ts — shared conformance kit for driver authors + bundled drivers.
|
|
3
|
+
*
|
|
4
|
+
* `runConformanceKit({ manifest, driverModule })` returns a structured pass/fail
|
|
5
|
+
* report. Used by the four bundled drivers' tests (ST07–ST09). Re-exposed
|
|
6
|
+
* via the driver-sdk public surface for re-extraction readiness — see
|
|
7
|
+
* driver-sdk/index.ts header.
|
|
8
|
+
*
|
|
9
|
+
* Checks:
|
|
10
|
+
* 1. Every declared capability in manifest.capabilities[] has a matching
|
|
11
|
+
* function export on driverModule.
|
|
12
|
+
* 2. Every function export returns a VerbResult-shaped object when invoked
|
|
13
|
+
* with a dummy arg (status, evidence_paths, duration_ms, retry_count).
|
|
14
|
+
* 3. The manifest's transport field is structured (not a raw string).
|
|
15
|
+
* 4. The manifest's trust.tier is one of the four allowed values.
|
|
16
|
+
*/
|
|
17
|
+
import type { DriverModule } from './idl.js';
|
|
18
|
+
import type { DriverManifest } from './manifest.js';
|
|
19
|
+
export interface ConformanceCheck {
|
|
20
|
+
readonly id: string;
|
|
21
|
+
readonly description: string;
|
|
22
|
+
readonly status: 'pass' | 'fail';
|
|
23
|
+
readonly detail?: string;
|
|
24
|
+
}
|
|
25
|
+
export interface ConformanceReport {
|
|
26
|
+
readonly driver_id: string;
|
|
27
|
+
readonly version: string;
|
|
28
|
+
readonly overall: 'pass' | 'fail';
|
|
29
|
+
readonly checks: readonly ConformanceCheck[];
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Run the conformance kit against a driver. Pass `dummyArgs` to control the
|
|
33
|
+
* fixture invocation; default is an empty object (most drivers ignore args
|
|
34
|
+
* in conformance mode and return a stub VerbResult).
|
|
35
|
+
*/
|
|
36
|
+
export declare function runConformanceKit(opts: {
|
|
37
|
+
manifest: DriverManifest;
|
|
38
|
+
driverModule: DriverModule;
|
|
39
|
+
dummyArgs?: Record<string, unknown>;
|
|
40
|
+
}): Promise<ConformanceReport>;
|
|
41
|
+
//# sourceMappingURL=conformance.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conformance.d.ts","sourceRoot":"","sources":["../../src/driver-sdk/conformance.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAE5C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAEnD,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAA;IAChC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CACxB;AAED,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAA;IACjC,QAAQ,CAAC,MAAM,EAAE,SAAS,gBAAgB,EAAE,CAAA;CAC5C;AA2BD;;;;GAIG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE;IAC7C,QAAQ,EAAE,cAAc,CAAA;IACxB,YAAY,EAAE,YAAY,CAAA;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACnC,GAAG,OAAO,CAAC,iBAAiB,CAAC,CA8E7B"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* conformance.ts — shared conformance kit for driver authors + bundled drivers.
|
|
3
|
+
*
|
|
4
|
+
* `runConformanceKit({ manifest, driverModule })` returns a structured pass/fail
|
|
5
|
+
* report. Used by the four bundled drivers' tests (ST07–ST09). Re-exposed
|
|
6
|
+
* via the driver-sdk public surface for re-extraction readiness — see
|
|
7
|
+
* driver-sdk/index.ts header.
|
|
8
|
+
*
|
|
9
|
+
* Checks:
|
|
10
|
+
* 1. Every declared capability in manifest.capabilities[] has a matching
|
|
11
|
+
* function export on driverModule.
|
|
12
|
+
* 2. Every function export returns a VerbResult-shaped object when invoked
|
|
13
|
+
* with a dummy arg (status, evidence_paths, duration_ms, retry_count).
|
|
14
|
+
* 3. The manifest's transport field is structured (not a raw string).
|
|
15
|
+
* 4. The manifest's trust.tier is one of the four allowed values.
|
|
16
|
+
*/
|
|
17
|
+
import { isVerbResult } from './idl.js';
|
|
18
|
+
const ALLOWED_TRUST_TIERS = new Set([
|
|
19
|
+
'first_party_signed',
|
|
20
|
+
'community_verified',
|
|
21
|
+
'community_unverified',
|
|
22
|
+
'local_unverified',
|
|
23
|
+
]);
|
|
24
|
+
function isStructuredTransport(t) {
|
|
25
|
+
if (t === null || typeof t !== 'object' || Array.isArray(t))
|
|
26
|
+
return false;
|
|
27
|
+
const obj = t;
|
|
28
|
+
if (typeof obj.mcp_server_id === 'string')
|
|
29
|
+
return true;
|
|
30
|
+
if (typeof obj.http_endpoint === 'string')
|
|
31
|
+
return true;
|
|
32
|
+
if (typeof obj.npm_package === 'string')
|
|
33
|
+
return true;
|
|
34
|
+
if (obj.builtin === true)
|
|
35
|
+
return true;
|
|
36
|
+
if (obj.local_command !== null &&
|
|
37
|
+
typeof obj.local_command === 'object' &&
|
|
38
|
+
!Array.isArray(obj.local_command)) {
|
|
39
|
+
const lc = obj.local_command;
|
|
40
|
+
return typeof lc.binary === 'string' && Array.isArray(lc.args);
|
|
41
|
+
}
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Run the conformance kit against a driver. Pass `dummyArgs` to control the
|
|
46
|
+
* fixture invocation; default is an empty object (most drivers ignore args
|
|
47
|
+
* in conformance mode and return a stub VerbResult).
|
|
48
|
+
*/
|
|
49
|
+
export async function runConformanceKit(opts) {
|
|
50
|
+
const { manifest, driverModule } = opts;
|
|
51
|
+
const dummyArgs = opts.dummyArgs ?? { target: { kind: 'css', value: '#stub' } };
|
|
52
|
+
const checks = [];
|
|
53
|
+
// Check 1: structured transport
|
|
54
|
+
checks.push({
|
|
55
|
+
id: 'transport-structured',
|
|
56
|
+
description: 'manifest.transport must be a structured oneOf, never a raw string',
|
|
57
|
+
status: isStructuredTransport(manifest.transport) ? 'pass' : 'fail',
|
|
58
|
+
detail: isStructuredTransport(manifest.transport)
|
|
59
|
+
? undefined
|
|
60
|
+
: `transport is not a structured variant: ${JSON.stringify(manifest.transport)}`,
|
|
61
|
+
});
|
|
62
|
+
// Check 2: trust tier is one of the four allowed
|
|
63
|
+
checks.push({
|
|
64
|
+
id: 'trust-tier-allowed',
|
|
65
|
+
description: 'manifest.trust.tier must be one of the four allowed values',
|
|
66
|
+
status: ALLOWED_TRUST_TIERS.has(manifest.trust?.tier) ? 'pass' : 'fail',
|
|
67
|
+
detail: ALLOWED_TRUST_TIERS.has(manifest.trust?.tier)
|
|
68
|
+
? undefined
|
|
69
|
+
: `trust.tier="${manifest.trust?.tier}" not in ${[...ALLOWED_TRUST_TIERS].join(', ')}`,
|
|
70
|
+
});
|
|
71
|
+
// Check 3: capabilities length >= 5
|
|
72
|
+
checks.push({
|
|
73
|
+
id: 'capabilities-min-five',
|
|
74
|
+
description: 'manifest.capabilities must declare at least 5 IDL verbs',
|
|
75
|
+
status: manifest.capabilities.length >= 5 ? 'pass' : 'fail',
|
|
76
|
+
detail: manifest.capabilities.length >= 5
|
|
77
|
+
? undefined
|
|
78
|
+
: `only ${manifest.capabilities.length} capabilities declared`,
|
|
79
|
+
});
|
|
80
|
+
// Check 4: every declared capability has a function export
|
|
81
|
+
for (const cap of manifest.capabilities) {
|
|
82
|
+
const fn = driverModule[cap];
|
|
83
|
+
const ok = typeof fn === 'function';
|
|
84
|
+
checks.push({
|
|
85
|
+
id: `capability-export-${cap}`,
|
|
86
|
+
description: `manifest.capabilities[${cap}] has a matching function export`,
|
|
87
|
+
status: ok ? 'pass' : 'fail',
|
|
88
|
+
detail: ok ? undefined : `driverModule.${cap} is not a function`,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
// Check 5: every declared capability returns a VerbResult shape
|
|
92
|
+
for (const cap of manifest.capabilities) {
|
|
93
|
+
const fn = driverModule[cap];
|
|
94
|
+
if (typeof fn !== 'function')
|
|
95
|
+
continue; // already failed Check 4
|
|
96
|
+
try {
|
|
97
|
+
const result = await fn(dummyArgs);
|
|
98
|
+
const ok = isVerbResult(result);
|
|
99
|
+
checks.push({
|
|
100
|
+
id: `capability-shape-${cap}`,
|
|
101
|
+
description: `driver.${cap}() returns a VerbResult shape`,
|
|
102
|
+
status: ok ? 'pass' : 'fail',
|
|
103
|
+
detail: ok ? undefined : `return shape: ${JSON.stringify(result)}`,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
catch (err) {
|
|
107
|
+
checks.push({
|
|
108
|
+
id: `capability-shape-${cap}`,
|
|
109
|
+
description: `driver.${cap}() returns a VerbResult shape`,
|
|
110
|
+
status: 'fail',
|
|
111
|
+
detail: `threw: ${err instanceof Error ? err.message : String(err)}`,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
const overall = checks.every((c) => c.status === 'pass') ? 'pass' : 'fail';
|
|
116
|
+
return {
|
|
117
|
+
driver_id: manifest.driverId,
|
|
118
|
+
version: manifest.version,
|
|
119
|
+
overall,
|
|
120
|
+
checks,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=conformance.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conformance.js","sourceRoot":"","sources":["../../src/driver-sdk/conformance.ts"],"names":[],"mappings":"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"}
|