Project onboarding and manifest resolution
Phase 3 introduces the catalog, deterministic discovery, and canonical project manifest. Repository content remains untrusted until a person accepts a proposal.
Trust boundary
user-selected directory | vcanonical root + containment checks | vfixed-file scanners (read only, <= 1 MiB) | vevidence with source path and line range | vdeterministic proposal + validation | vhuman approval -> trusted immutable snapshotScanning never executes repository commands. It does not read .env, private
keys, credentials, arbitrary home-directory files, or symlinks that escape the
selected root. The Compose scanner decodes service and port declarations but
does not return environment values. The Node scanner proposes package-manager
commands from script names rather than copying script bodies. README evidence
is limited to the first title and credential-like text is redacted.
Each scanner is an independent evidence producer. The proposal builder has no
filesystem access and combines evidence using stable rules. Missing or
ambiguous runtime facts remain in unresolved; unresolved proposals cannot be
accepted.
Durable review model
A scan atomically creates a pending project, manifest proposal, and normalized
evidence rows. Repeating add for the same canonical root returns the existing
proposal instead of creating competing registrations. Approval uses a
compare-and-swap status transition and one SQLite transaction to:
- accept the proposal;
- supersede an older accepted proposal, if present;
- append an immutable manifest snapshot;
- increment the project manifest revision;
- change the project trust state to
trusted; and - append a mutation audit event.
No repository file is written by scanning or approval.
Canonical contract and precedence
internal/manifest/domain.Manifest is the source of truth for the portable
manifest. tools/schema-gen generates and commits
internal/manifest/schema/project.schema.json; generated-artifact checks fail
when it drifts. YAML decoding rejects unknown fields and validation applies the
schema, domain invariants, canonical path containment, executable availability,
port rules, and health-check syntax.
Effective values merge in this order, with the later source winning:
- live deterministic discovery;
- accepted inference stored in SQLite;
.switchyard/project.yml;.switchyard/project.local.yml; and- a runtime override for the current operation.
The resolver retains the winning source for every leaf as a JSON Pointer.
switchyard manifest explain, diff, and validate expose the result through
the same generated local API used by the UI.