# App And Report Build Protocol

Read this when building a real app, report, migration probe, QA check, or customer deliverable on the Ed-Fi 1EdTech surface.

## Start with public docs

Before writing app code or a report:

1. Open the customer website quickstart.
2. Open the data dictionary entry for each resource.
3. Open the endpoint catalog if the app needs route discovery.
4. Open the architecture ITD for each platform-specific behavior you mention.

Do not read implementation source or database tables to complete a customer-facing workflow.

## Choose the smallest live proof

Pick one workflow that proves the user's job:

- Attendance proof: descriptor list, append-only daily/section attendance POST, `ack_id` + ETag confirmation, optional detail correction with `If-Match`, soft-delete retention.
- Descriptor proof: list governed values, create district-local value, replay idempotency key, filter by code value.
- Program proof: list or write the relevant program association through its documented collection.
- Transcript proof: list or write the relevant academic-record resource through its documented collection.
- Staff/calendar proof: list or write the relevant staff, bell schedule, calendar, or session collection through its documented collection.
- Bulk proof: start import/export jobs and read job evidence.
- Conformance proof: read `/ed-fi/conformance/evidence?evidence_id={evidence_id}&limit=1&offset=0` for named evidence rows.

If the workflow requires a resource the endpoint catalog does not expose, report a surface leak instead of inventing a private route.

## Data storage boundary

Generated apps store Ed-Fi domain data through the Ed-Fi surface only:

- attendance rows,
- discipline rows,
- transcript rows,
- program associations,
- staff rows,
- calendar rows,
- descriptors,
- drafts,
- imports,
- exports,
- conformance evidence.

Browser storage may hold UI choices, selected resource names, recent request handles, and redacted response summaries. It must not become a second Ed-Fi database.

## Report structure

Every generated report should include:

- Base URL and tenant mode.
- Exact endpoint paths called.
- HTTP status and key headers.
- Response IDs from the surface, especially `edfi_local_id`, `ack_id`, `ETag`, job ids, and evidence ids.
- Provenance links to customer website and data dictionary sections.
- A leak-check statement saying what was not implemented locally.

## UI requirements for apps

A useful Ed-Fi app should expose:

- Credential mode: demo token or operator token.
- Resource selector backed by `GET /` or endpoint catalog, not a hardcoded schema table. For a curl root check, call `$ED_FI_BASE_URL` without adding a trailing slash.
- Paging controls that choose offset mode or cursor mode, never both.
- Request trace with redacted tokens.
- Response panel preserving Problem JSON.
- Write forms generated from documented fields or task-specific sample payloads, not from an embedded UDM copy.
- Evidence export that contains API paths, response fields, and doc links, not secrets.

## Client behavior

Use these client rules:

- Follow `links.next` for paging when present.
- Read descriptor catalogs before descriptor-dependent writes.
- Use platform3 OneRoster sourcedId overlay fields when the data dictionary requires them. `class_sourced_id` is canonical for class/section scope; `acmesis_class_sourced_id` and `section_sourced_id` are accepted only on writes and must read back as `class_sourced_id`.
- Use one `Idempotency-Key` per logical write.
- For attendance teacher marks, use append-only POSTs to daily/section attendance event collections, honor `attendanceWritePolicy.maxClientConcurrency` from `GET /` (currently 8), and report `ack_id` plus ETag as confirmation. A 32-student daily+section roster batch should not need an app-local cap beyond that published policy.
- Read detail and use `If-Match` before updates and deletes.
- Treat `edfi_local_id` as opaque.
- Treat `ack_id` as platform acknowledgement evidence, not as Ed-Fi natural identity.
- Treat soft-deleted records as retained audit evidence, not as records the app should purge locally.

## Stop conditions

Stop and report a surface leak when the app would need:

- local schema parsing to know field rules;
- local descriptor tables to validate a descriptor;
- dedup or conflict resolution outside idempotency and ETags;
- hard-delete behavior;
- private database access;
- roster identity that does not exist in OneRoster;
- an Alpha rename/cut/restrict/extend behavior on the 1EdTech surface.
