# Binary Leak Check

Run this before shipping any app, report, QA probe, or customer deliverable built with the Content Alpha skill pack.

Verdict is binary:

- PASS if every fact comes from Content Alpha API responses or canonical docs, and the client only formats those facts.
- FAIL if the pack or downstream artifact does work the surface promised to own.

## Runnable Pack Check

From the installed skill directory, run:

```bash
node checks/verify-skill-pack.mjs
```

Default behavior:

- Uses `CONTENT_BASE_URL` or the canonical implementation URL.
- Uses `CONTENT_TOKEN` for an operator-supplied tenant, or mints a demo token with `POST /dev/mint?tenantId=demo`.
- Reads the descriptor, assessment-component rows, article-by-curriculum list, selected article detail, student view, media, content references, curriculum links, catalog facets, effectiveness, trust, policies, Common Cartridge export metadata, and an unsupported-filter Problem JSON response.
- Performs static file-shape checks: no `scripts/`, `data/`, fixture, database, XML, ZIP, package-manager, or executable implementation files in the installable pack except this verifier.
- Prints JSON evidence with `result: "pass"` or exits non-zero.

The verifier is not app logic. It does not parse QTI, reconstruct assessment components, score, compute effectiveness, rewrite media URLs, copy catalog facet rows into an app, generate Common Cartridge bytes, inspect package internals, or maintain domain data. It only calls the surface and checks that the pack remains instructions-first. Its exact kind, role, and facet arrays are verifier-only contract goldens used to reject descriptor additions, omissions, and reorderings; downstream apps must read those values from the descriptor instead of importing or copying the goldens.

## Forbidden In The Skill Pack Or Downstream Artifact

Do not ship any of these:

- QTI XML/ZIP parsing, response-declaration parsing, answer-key extraction, assessment-component reconstruction, scoring-plan reconstruction, or media-path repair.
- Distractor, rubric, pre-authored feedback, question-ref, section, or part extraction from raw QTI/XML/JSONB/package files instead of `/assessment-components`.
- Content kind, subject, grade, test type, mastery gate, or source-system inference from titles, URLs, filenames, package paths, XML, or MIME extensions.
- Runtime or downstream enum/value tables copied from the data dictionary. Verifier-only exact contract goldens are allowed solely to detect descriptor drift and must never be imported into app logic.
- Catalog facet recomputation, local discovery indexes, LOR-specific storage, or sidecar rows inferred from Content base fields at read time.
- Referenced Content nested, copied, or hydrated inside a parent Content row instead of read through `content_reference` relationship rows and the referenced row's own endpoints.
- Expected XP averaging from student attempts, awarded-XP calculation, or local expected-XP banding outside the surface.
- Score calculation, result processing, student-answer persistence, attempt persistence, event logging, mastery/decay math, advancement math, report-card rollups, or gradebook state.
- Content-effectiveness counters, effectiveness-rate formulas, freshness-window formulas, or policy cutoffs.
- Curriculum graph reconstruction, curriculum-node deduplication, or curriculum/content links represented as tags instead of API relationship rows.
- Common Cartridge / IMSCP manifest construction, ZIP generation, round-trip validation, or package translation logic outside the export endpoint.
- Media URL rewriting, signed URL construction, storage bucket lookup, or credential query strings.
- Secrets, bearer tokens, or student app credentials stored in Content metadata, tags, local storage, or output files.
- Local persistence for Content domain rows that bypasses the surface.
- Private implementation source reads or database reads to complete a customer workflow.

## Required Evidence

For a passing deliverable, record:

1. Canonical docs opened.
2. Base URL used.
3. Credential path used: demo mint or operator-supplied token.
4. Exact endpoint calls made, or the response evidence the user can reproduce.
5. Any Problem JSON returned by the API.
6. Confirmation that no forbidden surface-owned logic was added.

This pack records its latest doer-side verification at `evidence/verification-latest.json`. Re-run the verifier after install because the live surface is the answer key.

## Stop Conditions

Stop and report a surface gap if the user job requires:

- Search or filters not documented by the generated data dictionary or service descriptor.
- A catalog facet key or value not available from `/catalog-facets` or the descriptor.
- An `expected_xp` or expected-XP band that the API does not return.
- Student answer submission or score persistence through Content.
- A content-effectiveness value the API does not return.
- A policy threshold not available from `/policies`.
- A media URL that can only be made to work by rewriting it locally.
- A QTI package interpretation that the import endpoint does not expose.
- An assessment section, part, question ref, distractor, rubric, or pre-authored feedback row not available from `/assessment-components`.
- A Common Cartridge package or round-trip proof that the export endpoint does not expose.
- A curriculum relationship that can only be represented as a tag.
- An embedded/supporting Content relationship that can only be represented by nesting one Content payload inside another.
- Any secret or credential value on a Content row.

When reporting a gap, cite the canonical URL and the missing endpoint, field, or behavior. Do not hide the gap with client code.
