# Worked Example: Attendance Workflow Proof

This example regenerates the same kind of proof the approved integration app exercised: demo auth, descriptor governance, roster-backed attendance write, grade write, detail reads, ETag patch, soft-delete, import/export evidence, and conformance evidence.

It calls the live surface only. It does not parse the Ed-Fi UDM, copy descriptor tables, reconcile roster ids, compute ETags, dedupe writes, or inspect implementation source.

## Inputs

```bash
export ED_FI_BASE_URL="${ED_FI_BASE_URL:-https://platform3-andymontgomery-9773s-projects.vercel.app/ed_fi/1edtech/implementation/api}"
export ED_FI_BASE_URL="${ED_FI_BASE_URL%/}"
```

This demo uses seeded demo roster anchors documented by the public customer website and verified by integration:

- `studentReference.studentUniqueId`: `student-001`
- `schoolReference.schoolId`: `255901001`
- `student_sourced_id`: `student-001`
- `school_sourced_id`: `school-north-valley`
- `acmesis_class_sourced_id` or `section_sourced_id`: `class-math7-p2` on write only; the surface stores and reads back canonical `class_sourced_id`

For a real tenant, replace these with roster anchors supplied by the tenant through OneRoster. Do not mint fallback roster identity.

## 1. Mint demo credentials

```bash
TOKEN_JSON="$(curl -fsS -X POST "$ED_FI_BASE_URL/dev/mint?tenantId=demo")"
export ED_FI_TOKEN="$(printf '%s' "$TOKEN_JSON" | jq -r '.token')"
```

If `jq` is unavailable, extract the `token` field with another JSON tool.

## Runnable proof replay

The pack ships a runnable proof check at `bin/proof-replay.sh`. Run it after install:

```bash
./bin/proof-replay.sh
```

It calls the same live API routes in this example and exits nonzero if the platform's returned answers do not match the documented assertions. The script contains shell assertions only; it does not copy Ed-Fi schema, descriptor values, roster reconciliation, ETags, idempotency replay, or soft-delete logic.

## 2. Confirm the live descriptor

```bash
curl -fsS "$ED_FI_BASE_URL" \
  -H "Authorization: Bearer $ED_FI_TOKEN" \
  | jq '{module, surface, edFiDataStandard, counts, routes, links}'
```

Expected proof points:

- module is Ed-Fi;
- route counts are present;
- documentation links point back to platform3 Ed-Fi docs.

Verified response excerpt on 2026-06-12:

```json
{
  "module": "ed_fi",
  "surface": "1edtech",
  "edFiDataStandard": "v6.1.0",
  "counts": {
    "total_routed_collections": 473,
    "canonical_resources": 193,
    "descriptor_catalogs": 280
  },
  "routes": {
    "resources": 193,
    "descriptors": 280,
    "conformanceEvidence": "/ed-fi/conformance/evidence",
    "demoMint": "/dev/mint?tenantId=demo"
  }
}
```

## 3. Read governed attendance descriptors

```bash
curl -fsS -D /tmp/edfi-attendance-descriptor.headers \
  "$ED_FI_BASE_URL/ed-fi/descriptors/attendanceEventCategoryDescriptors?codeValue=In%20Attendance&namespace=uri%3A%2F%2Fed-fi.org%2FAttendanceEventCategoryDescriptor&limit=5&offset=0" \
  -H "Authorization: Bearer $ED_FI_TOKEN" \
  -o /tmp/edfi-attendance-descriptor.json
```

Expected proof points:

- HTTP 200;
- `Total-Count` response header;
- JSON `totalCount` and `page.totalCount`;
- `page.offset` and `page.limit`;
- the filtered governed descriptor row returned by the surface, with namespace `uri://ed-fi.org/AttendanceEventCategoryDescriptor` and code value `In Attendance`.

Verified response excerpt on 2026-06-12:

```json
{
  "totalCountAtLeast": 1,
  "page": {"offset": 0, "limit": 5},
  "values": [{"namespace": "uri://ed-fi.org/AttendanceEventCategoryDescriptor", "codeValue": "In Attendance"}]
}
```

The proof script uses the same documented `codeValue` + `namespace` key filter. It never depends on descriptor ordering, unfiltered descriptor pages, or exact descriptor totals on the shared demo tenant.

Use a descriptor URI returned by the surface. The common Ed-Fi standard example is `uri://ed-fi.org/AttendanceEventCategoryDescriptor#In Attendance`; do not assume a district-local descriptor exists until the endpoint returns it.

For copy-paste proof runs, extract the returned standard descriptor URI:

```bash
export ATTENDANCE_DESCRIPTOR_URI="$(jq -r 'first(.data[] | select(.namespace == "uri://ed-fi.org/AttendanceEventCategoryDescriptor" and .codeValue == "In Attendance") | "\(.namespace)#\(.codeValue)")' /tmp/edfi-attendance-descriptor.json)"
```

## 4. Create a canonical attendance mark

Ordinary daily and section attendance marks are append-only POST events. Do not use `PUT` for the between-bells marking path. The root descriptor's `attendanceWritePolicy` publishes the current classroom cap: 32 students at no more than 8 concurrent POSTs, confirmed by `ack_id` plus ETag. Detail `PATCH`/`DELETE` below are correction and retention proofs for an already acknowledged row.

```bash
export RUN_ID="skill-$(date -u +%Y%m%dT%H%M%SZ)-$$-${RANDOM:-0}"
export ATTENDANCE_KEY="attendance-create-$RUN_ID"
curl -fsS -D /tmp/edfi-attendance-create.headers \
  -X POST "$ED_FI_BASE_URL/ed-fi/studentSchoolAttendanceEvents" \
  -H "Authorization: Bearer $ED_FI_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $ATTENDANCE_KEY" \
  --data '{
    "studentReference": {"studentUniqueId": "student-001"},
    "schoolReference": {"schoolId": 255901001},
    "sessionReference": {"schoolYear": 2026, "sessionName": "Spring Semester"},
    "attendanceEvent": {
      "eventDate": "2026-06-03",
      "attendanceEventCategoryDescriptor": "'"$ATTENDANCE_DESCRIPTOR_URI"'"
    },
    "schoolAttendanceDuration": 390,
    "student_sourced_id": "student-001",
    "school_sourced_id": "school-north-valley",
    "acmesis_class_sourced_id": "class-math7-p2"
  }' \
  -o /tmp/edfi-attendance-create.json
```

Expected proof points:

- HTTP 201;
- response body contains `data.edfi_local_id`;
- response body contains `data.ack_id`;
- response header contains `ETag`;
- response headers include `X-Platform3-Attendance-Policy: edfi.attendance.teacher_mark.v2026-06-22`, `X-Platform3-Write-Path: teacher-mark-create`, and `X-Platform3-Max-Client-Concurrency: 8`;
- response data includes the roster overlay fields if the route touches roster identity;
- `acmesis_class_sourced_id` and `section_sourced_id` are not read back; they normalize to canonical `class_sourced_id`.

Extract `data.edfi_local_id` and the current `ETag` with your JSON/header tools.

```bash
export EDFI_LOCAL_ID="$(jq -r '.data.edfi_local_id' /tmp/edfi-attendance-create.json)"
export EDFI_ETAG="$(grep -i '^etag:' /tmp/edfi-attendance-create.headers | sed 's/^[Ee][Tt][Aa][Gg]:[[:space:]]*//' | tr -d '\r')"
```

These shell extracts are only handling response values. They are not Ed-Fi business logic.

## 5. Read detail by platform local id

```bash
curl -fsS -D /tmp/edfi-attendance-detail.headers \
  "$ED_FI_BASE_URL/ed-fi/studentSchoolAttendanceEvents/$EDFI_LOCAL_ID" \
  -H "Authorization: Bearer $ED_FI_TOKEN" \
  -o /tmp/edfi-attendance-detail.json
```

Expected proof points:

- the same `edfi_local_id`;
- current `ETag`;
- platform acknowledgement fields;
- no need to know the Ed-Fi natural key to read detail.

## 6. Patch with If-Match and idempotency

```bash
export PATCH_KEY="attendance-patch-$RUN_ID"
curl -fsS -D /tmp/edfi-attendance-patch.headers \
  -X PATCH "$ED_FI_BASE_URL/ed-fi/studentSchoolAttendanceEvents/$EDFI_LOCAL_ID" \
  -H "Authorization: Bearer $ED_FI_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $PATCH_KEY" \
  -H "If-Match: $EDFI_ETAG" \
  --data '{"schoolAttendanceDuration": 405}' \
  -o /tmp/edfi-attendance-patch.json
```

Expected proof points:

- HTTP 200;
- duration changed to 405;
- response provides the next current validator.

If the API returns `edfi:etag_mismatch`, refetch detail and retry intentionally. Do not calculate a replacement ETag.

## 7. Soft-delete and prove retention

```bash
export DELETE_ETAG="$(jq -r '.data.etag' /tmp/edfi-attendance-patch.json)"
export DELETE_KEY="attendance-delete-$RUN_ID"
curl -fsS -D /tmp/edfi-attendance-delete.headers \
  -X DELETE "$ED_FI_BASE_URL/ed-fi/studentSchoolAttendanceEvents/$EDFI_LOCAL_ID" \
  -H "Authorization: Bearer $ED_FI_TOKEN" \
  -H "Idempotency-Key: $DELETE_KEY" \
  -H "If-Match: $DELETE_ETAG" \
  -o /tmp/edfi-attendance-delete.json

curl -fsS "$ED_FI_BASE_URL/ed-fi/studentSchoolAttendanceEvents/$EDFI_LOCAL_ID?includeDeleted=true" \
  -H "Authorization: Bearer $ED_FI_TOKEN"
```

Expected proof points:

- DELETE returns 204;
- deleted readback returns the same `edfi_local_id`;
- record shows soft-delete metadata such as `is_deleted`.

Do not purge locally. Retention belongs to the surface.

## 8. Start import, export, and conformance evidence reads

```bash
IMPORT_STATUS="$(curl -sS -X POST "$ED_FI_BASE_URL/ed-fi/imports" \
  -H "Authorization: Bearer $ED_FI_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: import-$RUN_ID" \
  --data "{\"source_format\":\"edfi-json-bundle\",\"records\":[{\"resource_name\":\"StudentSchoolAttendanceEvent\",\"source_key_json\":{\"run_id\":\"$RUN_ID\"}}]}" \
  -o /tmp/edfi-import.json \
  -w "%{http_code}")"
test "$IMPORT_STATUS" = "202"

IMPORT_JOB_ID="$(jq -r '.data.import_job_id' /tmp/edfi-import.json)"
JOB_POLL_ATTEMPTS="${JOB_POLL_ATTEMPTS:-90}"
JOB_POLL_INTERVAL_SECONDS="${JOB_POLL_INTERVAL_SECONDS:-2}"
IMPORT_STARTED_AT="$(date -u +%s)"
for ((attempt = 1; attempt <= JOB_POLL_ATTEMPTS; attempt += 1)); do
  curl -fsS "$ED_FI_BASE_URL/ed-fi/imports/$IMPORT_JOB_ID" \
    -H "Authorization: Bearer $ED_FI_TOKEN" \
    -o /tmp/edfi-import-terminal.json
  IMPORT_STATE="$(jq -r '.data.state // "unknown"' /tmp/edfi-import-terminal.json)"
  IMPORT_ELAPSED="$(($(date -u +%s) - IMPORT_STARTED_AT))"
  printf 'import poll attempt=%d/%d state=%s elapsed=%ss\n' "$attempt" "$JOB_POLL_ATTEMPTS" "$IMPORT_STATE" "$IMPORT_ELAPSED" >&2
  jq -e '.data.state == "completed" and .data.row_count == 1 and .data.error_count == 0' /tmp/edfi-import-terminal.json >/dev/null && break
  if [ "$attempt" -lt "$JOB_POLL_ATTEMPTS" ]; then
    sleep "$JOB_POLL_INTERVAL_SECONDS"
  fi
done
jq -e '.data.state == "completed" and .data.row_count == 1 and .data.error_count == 0 and .links.dataDictionary' /tmp/edfi-import-terminal.json

EXPORT_STATUS="$(curl -sS -X POST "$ED_FI_BASE_URL/ed-fi/exports" \
  -H "Authorization: Bearer $ED_FI_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: export-$RUN_ID" \
  --data '{"export_scope":"complete-model","modified_since":"2026-06-01T00:00:00Z"}' \
  -o /tmp/edfi-export.json \
  -w "%{http_code}")"
test "$EXPORT_STATUS" = "202"

EXPORT_JOB_ID="$(jq -r '.data.export_job_id' /tmp/edfi-export.json)"
EXPORT_STARTED_AT="$(date -u +%s)"
for ((attempt = 1; attempt <= JOB_POLL_ATTEMPTS; attempt += 1)); do
  curl -fsS "$ED_FI_BASE_URL/ed-fi/exports/$EXPORT_JOB_ID" \
    -H "Authorization: Bearer $ED_FI_TOKEN" \
    -o /tmp/edfi-export-terminal.json
  EXPORT_STATE="$(jq -r '.data.state // "unknown"' /tmp/edfi-export-terminal.json)"
  EXPORT_ELAPSED="$(($(date -u +%s) - EXPORT_STARTED_AT))"
  printf 'export poll attempt=%d/%d state=%s elapsed=%ss\n' "$attempt" "$JOB_POLL_ATTEMPTS" "$EXPORT_STATE" "$EXPORT_ELAPSED" >&2
  jq -e '.data.state == "completed" and .data.export_scope == "complete-model" and .data.redaction_summary_json.secrets == 0' /tmp/edfi-export-terminal.json >/dev/null && break
  if [ "$attempt" -lt "$JOB_POLL_ATTEMPTS" ]; then
    sleep "$JOB_POLL_INTERVAL_SECONDS"
  fi
done
jq -e '.data.state == "completed" and .data.export_scope == "complete-model" and .data.redaction_summary_json.secrets == 0 and .links.dataDictionary' /tmp/edfi-export-terminal.json

for EVIDENCE_ID in \
  evidence-descriptor-governance-v6-1 \
  evidence-http-contract-edfi \
  evidence-udm-coverage-v6-1; do
  curl -fsS "$ED_FI_BASE_URL/ed-fi/conformance/evidence?evidence_id=$EVIDENCE_ID&limit=1&offset=0" \
    -H "Authorization: Bearer $ED_FI_TOKEN"
done
```

Expected proof points:

- import and export each return HTTP 202;
- import returns `data.import_job_id`, then its detail route reaches `data.state: "completed"` with `row_count: 1`, `error_count: 0`, and dictionary/provenance links;
- export returns `data.export_job_id`, then its detail route reaches `data.state: "completed"`, `data.export_scope: "complete-model"`, and privacy redaction summary;
- conformance endpoint returns each named evidence row through an exact `evidence_id` filter, with `passed: true` and data-dictionary provenance.

## 9. Grades exporter proof

This second resource family proves the pack generalizes beyond attendance. It reads governed grade descriptors, creates a grade, reads it back by platform local id, then soft-deletes it and proves retention. It still calls the surface only.

```bash
curl -fsS "$ED_FI_BASE_URL/ed-fi/descriptors/gradeTypeDescriptors?codeValue=Final&namespace=uri%3A%2F%2Fed-fi.org%2FGradeTypeDescriptor&limit=5&offset=0" \
  -H "Authorization: Bearer $ED_FI_TOKEN" \
  -o /tmp/edfi-grade-type-descriptors.json

jq '{totalCount, values: [.data[] | {namespace, codeValue}]}' /tmp/edfi-grade-type-descriptors.json
```

Expected result assertion:

```json
{
  "totalCountAtLeast": 1,
  "valuesInclude": [{"namespace": "uri://ed-fi.org/GradeTypeDescriptor", "codeValue": "Final"}]
}
```

The exact server-side filter returns the standard governed value. Assert the returned row's namespace and code value instead of relying on a page of an unfiltered descriptor collection.

Use the returned descriptor URI in the grade write:

```bash
export GRADE_TYPE_DESCRIPTOR_URI="$(jq -r 'first(.data[] | select(.namespace == "uri://ed-fi.org/GradeTypeDescriptor" and .codeValue == "Final") | "\(.namespace)#\(.codeValue)")' /tmp/edfi-grade-type-descriptors.json)"
```

Create a grade:

```bash
export GRADE_KEY="grade-create-$RUN_ID"
cat > /tmp/edfi-grade-create.payload.json <<JSON
{
  "gradeTypeDescriptor": "$GRADE_TYPE_DESCRIPTOR_URI",
  "studentSectionAssociationReference": {
    "studentUniqueId": "student-001",
    "schoolId": 255901001,
    "localCourseCode": "SKILL-$RUN_ID",
    "schoolYear": 2026,
    "sectionIdentifier": "SKILL-$RUN_ID",
    "sessionName": "Spring Semester",
    "beginDate": "2026-01-15"
  },
  "gradingPeriodReference": {
    "gradingPeriodDescriptor": "uri://ed-fi.org/GradingPeriodDescriptor#End of Year",
    "periodSequence": 2,
    "schoolId": 255901001,
    "schoolYear": 2026
  },
  "letterGradeEarned": "A",
  "numericGradeEarned": 95.5,
  "currentGradeIndicator": false,
  "currentGradeAsOfDate": "2026-06-03"
}
JSON

curl -fsS -D /tmp/edfi-grade-create.headers \
  -X POST "$ED_FI_BASE_URL/ed-fi/grades" \
  -H "Authorization: Bearer $ED_FI_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $GRADE_KEY" \
  --data @/tmp/edfi-grade-create.payload.json \
  -o /tmp/edfi-grade-create.json
```

Expected result assertions:

- HTTP 201;
- response body contains `data.edfi_local_id`;
- response body contains `data.ack_id`;
- response header contains `ETag`;
- `data.numericGradeEarned` is `95.5`;
- `data.links.dataDictionary` points to the Ed-Fi data dictionary entry for Grade.

Read and soft-delete the grade:

```bash
export GRADE_LOCAL_ID="$(jq -r '.data.edfi_local_id' /tmp/edfi-grade-create.json)"
export GRADE_ETAG="$(grep -i '^etag:' /tmp/edfi-grade-create.headers | sed 's/^[Ee][Tt][Aa][Gg]:[[:space:]]*//' | tr -d '\r')"

curl -fsS "$ED_FI_BASE_URL/ed-fi/grades/$GRADE_LOCAL_ID" \
  -H "Authorization: Bearer $ED_FI_TOKEN" \
  -o /tmp/edfi-grade-detail.json

curl -fsS -X DELETE "$ED_FI_BASE_URL/ed-fi/grades/$GRADE_LOCAL_ID" \
  -H "Authorization: Bearer $ED_FI_TOKEN" \
  -H "Idempotency-Key: grade-delete-$RUN_ID" \
  -H "If-Match: $GRADE_ETAG"

curl -fsS "$ED_FI_BASE_URL/ed-fi/grades/$GRADE_LOCAL_ID?includeDeleted=true" \
  -H "Authorization: Bearer $ED_FI_TOKEN" \
  -o /tmp/edfi-grade-deleted.json
```

Expected result assertions:

- detail read returns the same `edfi_local_id`;
- DELETE returns 204;
- deleted readback returns the same `edfi_local_id`;
- deleted readback has `data.is_deleted: true` and `data.deleted_at`.

## Output template

When turning this proof into a report, include:

- base URL and tenant mode;
- each endpoint called;
- response statuses and key headers;
- `edfi_local_id`, `ack_id`, job ids, `ETag`, `Total-Count`, and Problem codes where present;
- attendance proof and grade proof result assertions, or the `bin/proof-replay.sh` JSON summary;
- links to the customer website and data dictionary;
- the leak-check result: no UDM parser, descriptor table, roster reconciliation, ETag calculation, idempotency replay, hard-delete, or private DB access was added.
