I3169 — A new pack enters campaigns/ through one command that checks the archive before writing a byte
Add a campaign add command that reads a ZIP or directory with limits on member count, sizes, decompression ratio, nesting, path traversal and symlinks, writes the pack verbatim, appends campaigns/MANIFEST.sha256 and the campaign index member, and executes nothing it contains.
BLOCKED wave 1 · p2 · implementation profile · parallel safe
Part of campaigns-are-read-as-provenance — A prompt pack is a campaign the index serves and the plan cites.
Blocked. This issue cannot start until I3167 is done. The status is derived from that, not declared.
Objective
Add a campaign add command that reads a ZIP or directory with limits on member count, sizes, decompression ratio, nesting, path traversal and symlinks, writes the pack verbatim, appends campaigns/MANIFEST.sha256 and the campaign index member, and executes nothing it contains.
Why
ADR 0124 point 6 (untrusted content, ZIP safety); the 2026-10-10 design separated ingestion from authorisation to execute; owner 2026-10-13: packs carry a schema, prompts and instructions. Proposed in ADR 0180 (A prompt pack is a campaign: kept as received, indexed as a kind, and cited by the records it drove) (proposed; it carries no authority until the owner accepts it). Sources: chatgpt-majordomus:c210#4, chatgpt-majordomus:c245#6.
Current state
Packs are copied in by hand and checked by campaigns-check afterwards.
Desired state
One safe command; the same check refuses a hand copy that breaks it.
Scope
- apps/majordomus-cli/src/cli.rs
- share/commands.yaml
- scripts/ci/campaigns-check
- campaigns/README.md
- apps/majordomus-cli/src/commands/mod.rs
- apps/majordomus-cli/Cargo.toml
- apps/majordomus-cli/Cargo.lock
- test/cases/340_a_brief_is_kept_as_received.sh
Out of scope
- Network fetches
- Running prompts
Dependencies
What waits on this
Acceptance criteria
- Each unsafe archive shape is refused before a write
- A safe pack lands with manifest and index rows
- Each new case named here takes its number from `scripts/case-numbers next` and is announced on the board before the file is written (ADR 0053); a case number written in this record before that is provisional
Validation
- bash test/run.sh 340_a_brief_is_kept_as_received
Evidence required
- case_pack_checked_before_kept
Evidence
None recorded. Every token above needs a command or an artifact behind it before this issue can be completed; narrative is refused.
Timeline
- started
- —
- verified
- —
- completed
- —
Those three fields, the evidence above and the state of the dependencies are all the status is made of. There is no status field to disagree with them.
Canonical record: .ai/repo/project/issues/I3169.yaml. Read it back with majordomus plan show I3169.