Conspectus resource
Specification status
Specification only. The Conspectus HTTP API is not implemented in the
application code yet. This hub is the working product narrative: data shapes, intended paths, and idempotency
ideas. After the API spec is finalized, implementation and OpenAPI will follow.
Single entry point for the ETR conspectus (study note): what the learner
produces in the human workflow, how that maps to JSON fields, and how HTTP methods are expected to fit
together. Human methodology (not normative for field shapes): Methodology.
Business context
A conspectus is a saved study note created after a learning session. Our methodology
uses a 3-step process: Extract (pull cues from content), Transform (write
a summary paragraph and bullet points). The API stores this package, along with scheduling info:
slot (A–D ladder), next_review_at, and an optional title.
Retrieval is planned via API endpoints for due and review; slot movement will live in a
dedicated schedule policy module once implemented.
Each conspectus is owned by a User identified by the
(system_user_id, system_uuid) pair (in requests or query params)—the same key as the User.
From study notes to API fields
The methodology uses a three-column cue sheet during Extract. The HTTP
body
splits that work into: (1) everything from the cue sheet → cue_sheet (JSON object); (2)
Transform
output → dense_paragraph and bullets; (3) optional heading for the whole note →
title. Identity → system_user_id + system_uuid (see
Data contract).
Recommended cue_sheet shape (explicit routing)
The API accepts any JSON object for cue_sheet. For clarity across clients
and
docs, this hub uses one documented convention: one array rows, each element
is
one horizontal row of the paper table; inside each element, three string fields match the three columns
left
to right.
Index n: the first data row on paper is n = 0 (first element of
rows), the second row is n = 1, and so on. Order in the array is top-to-bottom
as
on
the sheet.
Optional string cue_sheet.topic repeats the session theme inside the Extract
payload; you can also set the API field title for the whole conspectus (list views, cards).
They
may match (as in the example below) or differ if your product needs it.
Real cue sheet → cue_sheet JSON (same content)
Below, the left column is what a learner might actually fill in on paper during
Extract (one horizontal line = one idea). The right column is the same
information as the cue_sheet object you send in the API — no extra fields, only structure.
First line on paper = rows[0], next = rows[1], top to bottom. Use the property
names keywords, question, hint (not ad-hoc kw /
q abbreviations) so different clients agree on one shape.
On paper (three columns)
Topic on paper (optional): “Water cycle” — also fits
cue_sheet.topic below
| Keywords |
Questions |
Hints |
| evaporation |
What drives water into vapor? |
Sun heats surface |
| condensation |
Where do clouds form? |
Cooling air |
| precipitation |
Rain vs snow depends on? |
Temperature aloft |
In JSON (cue_sheet only)
{
"topic": "Water cycle",
"rows": [
{
"keywords": "evaporation",
"question": "What drives water into vapor?",
"hint": "Sun heats surface"
},
{
"keywords": "condensation",
"question": "Where do clouds form?",
"hint": "Cooling air"
},
{
"keywords": "precipitation",
"question": "Rain vs snow depends on?",
"hint": "Temperature aloft"
}
]
}
- Row 1 of the table →
rows[0] — left cell =
rows[0].keywords, middle = rows[0].question, right =
rows[0].hint.
- Row 2 →
rows[1], row 3 → rows[2] — same
rule.
- Optional session theme: either only
cue_sheet.topic here, or repeat it in the request
field title for lists (see worked example).
Data contract (summary)
Full schemas are in OpenAPI; this table is the shorthand for reviews and client onboarding.
| Field |
What the learner meant |
API notes |
system_user_id, system_uuid |
Which account this note belongs to (from your integration). |
Required on create / due / patch / review / errors; must match an existing user. |
title |
Optional short label (chapter, topic). |
Omit or string; max length per OpenAPI. |
cue_sheet |
The lean capture from Extract (e.g. rows with keyword / question / hint). |
Arbitrary JSON object (not an array at the top level). Must be valid JSON. |
dense_paragraph |
Transform: one paragraph in their own words, sources closed. |
Required non-empty string. |
bullets |
Transform: bullet list explaining the idea simply. |
Array of non-empty strings; typical length 5–7 in methodology docs. |
slot, next_review_at, … |
Scheduling — usually not typed by the user on create. |
Set by server from SchedulePolicy; updated on review. |
Worked example
Scenario: the learner studied the water cycle (evaporation,
condensation,
precipitation). They already have a user with the same (system_user_id, system_uuid) in our
database. Below is a realistic POST /api/v1/conspectuses body: the cue_sheet object
is the same as in the paper ↔ JSON example above (three rows); add
dense_paragraph and bullets for the Transform layer.
{
"system_user_id": "learner-01",
"system_uuid": "b2c3d4e5-0002-4000-8000-000000000002",
"title": "The water cycle",
"cue_sheet": {
"topic": "Water cycle",
"rows": [
{
"keywords": "evaporation",
"question": "What drives water into vapor?",
"hint": "Sun heats surface"
},
{
"keywords": "condensation",
"question": "Where do clouds form?",
"hint": "Cooling air"
},
{
"keywords": "precipitation",
"question": "Rain vs snow depends on?",
"hint": "Temperature aloft"
}
]
},
"dense_paragraph": "The sun heats oceans and lakes so water evaporates. Rising vapor cools and condenses into clouds. When droplets or ice grow heavy enough, water returns as rain or snow.",
"bullets": [
"Evaporation moves water from surface to atmosphere.",
"Condensation forms clouds when air cools.",
"Precipitation completes the loop back to Earth.",
"Energy from the sun drives the cycle.",
"The same water moves through states and locations over time."
]
}
After 201 Created, the response includes conspectus_uuid, slot
(starts at
A), next_review_at, and timestamps. Use Idempotency-Key on this
POST
as for
other critical writes.
Method pages (per endpoint)
Navigation matches HTTP method + path (how clients are expected to call the API). Planned
operationId names appear in the table; OpenAPI will be generated when routes exist.
Use the sidebar under API → Conspectus, or open a row below. Schedule summary (FR-5) is
documented here as a related read surface. The error log (/api/v1/errors, FR-4)
has a dedicated Error log hub — separate internal nav, same product
scope.
API surface
Planned conspectus routes share prefix /api/v1/conspectuses. Writes that change scheduling are
expected to use POST …/actions/review (command-style). When implemented, routes should require
X-API-Key and rate limiting per ADR 0005.
POST /api/v1/conspectuses
- operationId
createConspectus
- Idempotency
- Required
Idempotency-Key; path key /api/v1/conspectuses.
- Success
201 Created — full conspectus including conspectus_uuid,
slot, next_review_at.
GET /api/v1/conspectuses/due
- operationId
listDueConspectuses
- Idempotency
- Not used (read).
- Success
200 OK — JSON array of ConspectusResponse.
PATCH /api/v1/conspectuses/{conspectus_uuid}
- operationId
patchConspectus
- Idempotency
- Required; scope
PATCH /api/v1/conspectuses/{uuid} (per resource).
- Success
200 OK — updated ETR fields; scheduling unchanged.
POST
/api/v1/conspectuses/{conspectus_uuid}/actions/review
- operationId
reviewConspectus
- Idempotency
- Required; path includes concrete
conspectus_uuid (…/actions/review).
- Success
200 OK — updated conspectus body.
GET /api/v1/schedule/summary
- operationId
getScheduleSummary
- Idempotency
- Not used (read).
- Success
200 OK — slot histogram + due_now_count (aggregates conspectus rows).
Request path and layers
Middleware in app/main.py (metrics, body limit, API key + rate limit, security headers,
request
ID) → route handler → service → repository → SQLite. Writes that use idempotency also touch
idempotency_keys via IdempotencyRepository.
Technical overview
Current codebase: user identity and idempotency infrastructure only (app/api/v1/user.py,
shared middleware in app/main.py, SQLite via SQLITE_DB_PATH). Conspectus, schedule,
and error-log persistence are not present until the spec is implemented (new routers,
services, repositories, ORM models, and Alembic migrations).
Ownership and change management
Who changes this feature: contributors following
CONTRIBUTING.md — PRs on main, review, green CI.
-
Quality gate:
make verify-ci (lint, types, OpenAPI, contract tests, tests,
docs-check).
-
Contract: HTTP changes → code +
make openapi-accept-changes
(ADR 0007).
-
Internal narrative: update this hub and method pages when behavior or idempotency paths
change (ADR
0026).