# APS confirmed information — read contract 2.0.0

Authority: Development Charter `4a9134b056926afd4e55f332d34ca9b34943f21f`, `handoffs/aps-confirmed-item-aggregation-20261026/implementation-specification-c1.md` sections 2–6 and 10. This document specifies the Backend wire delta; it does not revise Task definitions, evaluation, payment, authentication, or the approved UI.

## Versions and immutable selection

New derived results use `analysis_policy_version=aps-confirmed-information.v1` and `aggregate_version=aps-aggregate.v2`. The saved root is `ln_church.aps_snapshot.v2`. Public and purchaser responses use `ln_church.aps_study.v2`, `ln_church.aps_answer.v2`, `ln_church.aps_answers.v2`, and `ln_church.aps_profile_analysis.v2`. All carry `snapshot_id`, policy/aggregate versions, `basis_time`, and `input_revisions`. Research revisions are `{task_id, source_revision}` entries in `research_tasks`; purchaser snapshots also contain `profile_tasks`. Public snapshots never include profile inputs or references.

Old snapshot IDs and answer cursors continue to select old objects and their original response versions. An old snapshot has no newly inferred item acceptance or fixed profile analysis. Legacy export identifies `aps-legacy-submission.v1`, retains the old aggregate version and flags, and uses null / `NOT_RECORDED` for absent new fields. A missing requested snapshot returns410; it does not resolve latest.

## Item acceptance and arithmetic

`row.analysis = {policy_version, aggregate_version, items}` is separate from unchanged `quality`, `content`, `analysis_eligible`, and `analysis_exclusion_reason`. Items retain assignment order and have `item_id, kind, included, reason, value, source_state, source_reason`. Kinds are NUMERIC, REPORT, PROFILE_ATTRIBUTE. Only included NUMERIC records contain an adopted numeric value; other values are null. No item acceptance is invented for deep-dive free text.

Each item requires its own saved valid q >0.30 and the applicable existing evaluation terminal boundary. Main evaluation uses FINAL entitlement as the terminal marker, not reward kind or payment success; optional model evaluation uses its independent completion. Zero / NO are valid. Numeric scores must already be saved and COMPLETE; no score is reconstructed from propositions. Non-scored reports/attributes can use their own saved quality and accepted structured state even when rejected overall content has no items. Normal unknown/non-disclosed nonnumeric states are included state information, not concrete votes/groups.

Exclusion vocabulary: `not_assigned, not_performed, unknown, not_disclosed, not_submitted, not_obtained, quality_rejected, quality_unavailable, score_unavailable, information_unavailable, ambiguous, evaluation_pending, invalid_saved_value`. Missing counts cover assigned accepted answers only. Read failures fail the operation rather than becoming missing items.

`aggregate.items[id]` preserves numerator, denominator, value, missing_reasons, source_tasks and availability. Axis1 keeps four item_denominators; axes2–5 keep complete_address_count. Person axes require four adopted items and personal total requires20. Service total requires five available axes. Context/wave boundaries and the sanctioned B/D combination remain; F values do not replace D. Paired changes use same-address/same-item intersections.

Reports add `item_counts.category` and `.competitors`, each containing `included_reports, concrete_votes, unknown_reports, excluded_reports, exclusion_reasons, unknown_url_candidates`. Votes are counted before display limits; category/competitor limits remain3/5 and ties retain their previous meaning. Unknown report count differs from unknown-URL candidate count. Existing fixed follow-up candidates are not rewritten.

Profile v2 uses the selected purchaser snapshot. `profile_state` is AVAILABLE / NOT_OBTAINED / NOT_RECORDED. `population` separates research_respondents and profile_respondents. Each of the five attributes has concrete groups, missing state counts, exclusion reasons, total_groups, total_pages, page and page_size. A group has key, label, respondents, timestamps and its intersected aggregate. Timestamps retain both profile and research receipt times and fixed source references. Missing/non-disclosed/pending attributes do not become concrete groups. Profile page_size is1–10; a page beyond every attribute's final page is400.

## Routes and proof

Application routes below use the existing `/api` prefix in browser clients.

| Operation | Request |
| --- | --- |
| Public study / answer pages / detail | Existing GET `/agent/aps/studies/{study_id}`, `/answers`, `/answers/{submission_id}`; retain snapshot_id and cursor |
| Public export page | GET `/agent/aps/studies/{study_id}/analysis-export?snapshot_id=...`; only snapshot_id, page, page_size, cursor |
| Purchaser study / answer pages / detail | Existing POST `/agent/aps/read` views and resource proof |
| Fixed profile analysis | POST read request v2, view=profile_analysis; query snapshot_id required, order_id required for study resource, optional page/page_size |
| Purchaser export page | POST read request v2, view=analysis_export; same query plus optional cursor |

V2 top-level fields are exactly `schema_version=ln_church.aps_read_request.v2, challenge_token, typed_data, signature, view` and optional query. Existing views remain order/study/answers/answer/profile/profile_analysis; analysis_export is v2-only. V1 profile_analysis remains the previous dynamic compatibility view, without new snapshot query fields. New profile/export clients must use v2 and the selected study snapshot.

Challenge format, EIP-712 domain/types/message, resource kind/id/payer, action/audience, keys, signature verification and300-second expiry are unchanged. Existing proof recovery applies; no export-specific signature or purchase is introduced. Order/study resource can access only its authorized order. Profile-task resource cannot access order-wide analysis/export. Current research and profile stop/deletion guards apply to their respective data; research display is not blocked solely by a stopped profile.

Error envelope remains `ln_church.aps_error.v1`: query/binding error400, read DTO structure422, proof invalid/expired401, unauthorized/private404, absent snapshot410 `snapshot_unavailable`, unavailable saved input503 `temporarily_unavailable`. No private existence explanation or partial success is returned.

## Export pages and file assembly

Page schema is `ln_church.aps_analysis_export_page.v1`. Common fields: snapshot_id, study_id, visibility PUBLIC/PURCHASER, analysis_policy_version, aggregate_version, basis_time, context_id, wave_id, input_revisions. Only purchaser output has order_id and PROFILE_GROUP records. Transport fields: page, page_size (10/25/50/100, default100), total_records, total_pages, records, first_cursor, previous_cursor, next_cursor, last_cursor. Snapshot ID remains mandatory with every cursor. Signed cursors bind study, snapshot, visibility/owner scope, export view, page size and page.

Records are ordered SUMMARY first, then research Task/submission and assigned item order, then profile attribute/group key order. SUMMARY exists even for a legitimate empty result. ITEM_CONTRIBUTION contains only numeric/report adoption and fixed references, not answer text, free-text reasons, profile text or raw provider payloads. Report contribution uses normalized keys and state/count information. Legacy contributions retain original legacy flags with new acceptance fields null. PROFILE_GROUP carries aggregated attributes and timestamps; each attribute has one key=null state-count record, followed by concrete groups whose state_counts/exclusion_reasons are null, preventing repeated state counts.

New snapshots persist a paged export projection before latest publication. Legacy export reads only the explicitly selected immutable snapshot and reuses a bounded in-process sanitized view; it never queries current history or recalculates legacy acceptance. Snapshot guards are checked for every page including cached legacy views.

The client must verify matching metadata/scope, total_records/total_pages, page sequence, cursor continuity and record counts across all pages before emitting one `ln_church.aps_analysis_export.v1` file. That file contains common metadata plus the complete ordered records, with no transport cursors, proof, token or S3 pointer. On failure, mismatch or selection change, discard the partial download. Use `aps-analysis-{study_id}-{snapshot_id}.json`; do not use display text as a filename.

`analysis.schema.json` defines new envelopes and added structures. Existing nested Task/answer/evaluation content, signed typed-data and legacy aggregates retain their existing contracts; this schema does not redefine those execution contracts. Backend constraints and authorization remain mandatory even when a syntactically valid JSON document passes schema validation.
