# People & Orgs Alpha Recipes

Each recipe calls the live surface only. Do not add raw database reads, local dedupe, term parsing, role inference, credential-secret handling, or local policy math.

## Setup

```bash
export PEOPLE_AND_ORGS_BASE_URL="${PEOPLE_AND_ORGS_BASE_URL:-https://platform3-andymontgomery-9773s-projects.vercel.app/people_and_orgs/alpha/implementation/api}"
export PEOPLE_AND_ORGS_TOKEN="${PEOPLE_AND_ORGS_TOKEN:-$(curl -fsS -X POST "$PEOPLE_AND_ORGS_BASE_URL/dev/mint?tenantId=demo" | jq -r '.token')}"
export AUTH_HEADER="Authorization: Bearer $PEOPLE_AND_ORGS_TOKEN"
```

## Teacher Roster For One School

Question: "Which students are in North Valley School as of 2026-09-15, and who guides the class?"

Calls:

```bash
curl -fsS "$PEOPLE_AND_ORGS_BASE_URL/places/place_north_valley_school/people?asOfDate=2026-09-15&roleKind=student" \
  -H "$AUTH_HEADER"

curl -fsS "$PEOPLE_AND_ORGS_BASE_URL/places/place_north_valley_school/people?asOfDate=2026-09-15&roleKind=guide" \
  -H "$AUTH_HEADER"

curl -fsS "$PEOPLE_AND_ORGS_BASE_URL/school_periods/period_fall_2026/active_memberships?asOfDate=2026-09-15" \
  -H "$AUTH_HEADER"
```

Use `/places/{schoolId}/people` as the source for the school roster. The active-period endpoint is period-wide; in a North Valley roster view, attach class and guide rows to the `person_id` values returned by the roster call. Do not infer a guide from the learning group name or a person's email, and do not add local dedupe logic if unexpected period rows appear.

## Students For One Guide

Question: "Which students does Katherine Johnson guide as of 2026-09-15?"

Call:

```bash
curl -fsS "$PEOPLE_AND_ORGS_BASE_URL/guides/person_katherine_johnson/students?asOfDate=2026-09-15" \
  -H "$AUTH_HEADER"
```

Use the returned `guide_person_id`, `student_person_id`, `learning_group_id`, `school_id`, `begin_date`, and `end_date` fields directly. Do not guess a route such as `/people/{personId}/students_for_guide`; the first-class inverse route is `/guides/{guidePersonId}/students`.

## School Calendar And School-Day Counts

Question: "Is a date a school day, how many school days are in a range, how many remain, and which reasons appear?"

Calls:

```bash
curl -fsS "$PEOPLE_AND_ORGS_BASE_URL/places/place_north_valley_school/school_calendar/2025-08-13" \
  -H "$AUTH_HEADER"

curl -fsS "$PEOPLE_AND_ORGS_BASE_URL/places/place_north_valley_school/school_calendar/2025-11-24" \
  -H "$AUTH_HEADER"

curl -fsS "$PEOPLE_AND_ORGS_BASE_URL/places/place_north_valley_school/school_calendar?startDate=2025-08-13&endDate=2026-07-24" \
  -H "$AUTH_HEADER" \
  | jq '{calendar_days:.count, school_days_between:.school_days_in_range, reason_values:([.data[].reason] | unique | sort)}'

curl -fsS "$PEOPLE_AND_ORGS_BASE_URL/places/place_north_valley_school/school_days_between?startDate=2025-08-13&endDate=2026-07-24" \
  -H "$AUTH_HEADER"

curl -fsS "$PEOPLE_AND_ORGS_BASE_URL/places/place_north_valley_school/school_days_remaining?asOfDate=2026-06-12" \
  -H "$AUTH_HEADER"
```

Calendar answers come from `alpha.school_calendar`, backed by Ed-Fi CalendarDate rows. Use `is_school_day` and `reason` as returned. The range response's `data[]` rows are the evidence for reason values; clients must not count weekdays, carry a holiday table, infer MAP testing windows, or maintain a copied reason enum.

## Student School Context

Question: "Where does Ada belong today?"

Calls:

```bash
curl -fsS "$PEOPLE_AND_ORGS_BASE_URL/people/person_ada_lovelace" -H "$AUTH_HEADER"
curl -fsS "$PEOPLE_AND_ORGS_BASE_URL/people/person_ada_lovelace/memberships?asOfDate=2026-09-15" -H "$AUTH_HEADER"
```

Display the returned `primary_place_id`, place memberships, class memberships, `role_kind`, `begin_date`, `end_date`, and `is_time_locatable`.

## NWEA Account Boundary

Question: "Which NWEA account does North Valley School belong to?"

Calls:

```bash
curl -fsS "$PEOPLE_AND_ORGS_BASE_URL/places?filter=placeKind==district&limit=20" -H "$AUTH_HEADER"
curl -fsS "$PEOPLE_AND_ORGS_BASE_URL/places/place_timeback_physical_district/schools" -H "$AUTH_HEADER"
```

Use the district response's `nwea_district_id`, `brand`, and `modality`. The district parent is the grouping grain. Do not reconstruct the account boundary from a school name or an NWEA export.

## Active Memberships During A School Period

Question: "Which place and class memberships are active during Fall 2026?"

Calls:

```bash
curl -fsS "$PEOPLE_AND_ORGS_BASE_URL/school_periods/period_fall_2026/active_memberships?asOfDate=2026-09-15" \
  -H "$AUTH_HEADER"
```

This endpoint applies the surface's point-in-time rules. Do not rebuild the null-start/null-end logic locally.
For a school-specific panel, start with rows whose returned `place_id` or `school_id` equals the selected school. For a roster-card panel, attach those rows to the people already returned by `/places/{schoolId}/people`. If extra rows appear in a shared demo tenant, report them as surface data drift; do not patch the drift with client-side dedupe or hidden hygiene rules.

## App Credential Status

Question: "Does Ada have an IXL Math credential reference, and when was it rotated?"

Calls:

```bash
curl -fsS "$PEOPLE_AND_ORGS_BASE_URL/app_credentials?filter=studentSourcedId==person_ada_lovelace" -H "$AUTH_HEADER"
curl -fsS "$PEOPLE_AND_ORGS_BASE_URL/app_credentials/person_ada_lovelace/ixl_math" -H "$AUTH_HEADER"
```

Render `app_id`, `has_credential`, and `last_rotated_at`. The absence of `secret_ref` is intentional.

## Sensitive Profile Read

Question: "What sensitive profile fields may this authorized caller see?"

Call:

```bash
curl -fsS "$PEOPLE_AND_ORGS_BASE_URL/person_sensitive_profiles/person_ada_lovelace" -H "$AUTH_HEADER"
```

Only call this for a job that needs sensitive profile data and has the right token scope. Ordinary roster views should not call it.

## Tag Registry And Policy Config

Questions:

- "Which governed tags are allowed?"
- "What tenure buckets and school-year policy should I use?"

Calls:

```bash
curl -fsS "$PEOPLE_AND_ORGS_BASE_URL/tag_definitions" -H "$AUTH_HEADER"
curl -fsS "$PEOPLE_AND_ORGS_BASE_URL/object_tags?filter=objectId==place_timeback_physical_district" -H "$AUTH_HEADER"
curl -fsS "$PEOPLE_AND_ORGS_BASE_URL/policy_config" -H "$AUTH_HEADER"
```

Use governed tags only for report slices. Do not use tags for relationships, and do not hardcode policy numbers in app code.

## Write Proof Pattern

For a write workflow:

1. Generate an `Idempotency-Key`.
2. `POST` one resource at a time.
3. `GET` detail and keep the returned `ETag`.
4. `PATCH` or `DELETE` with `If-Match` and another `Idempotency-Key`.
5. Re-read detail or the collection to confirm.

Do not bulk-import through Alpha. Bulk OneRoster work belongs on the OneRoster 1EdTech surface.

## Migration Reconciliation Pattern

Use public endpoints to answer customer-lived keys:

- roster count by `(school, roleKind, asOfDate)` via `/places/{placeId}/people`;
- membership count by `(period, asOfDate)` via `/school_periods/{periodId}/active_memberships`;
- NWEA account by school through `/places/{districtId}/schools`;
- app credential existence by `(student_sourced_id, app_id)` via `/app_credentials`.

If a migration check requires raw SQL, client-side dedupe, or source-name parsing, report a surface gap. Do not patch it inside the skill pack.
