# Journey: Nisaba notebook capture and citation export

Nisaba now participates in two durable browser paths. The legacy reading
workspace and notebook pages use one owner-scoped BFF snapshot; the Studio study
workspace uses a session-verifying proxy, the Yemaya study service, and a
Nisaba-owned Postgres notebook store. The legacy local note, six-format citation
builder, and id-ignoring specimen exporter remain separate browser authorities.
This journey preserves every shipped seam without presenting the two stores and
four clients as one stored-notebook-to-canonical-citation workflow.

## Personas

- **Close reader** — selects a public-domain passage and records a private or
  shared annotation with tags and a notebook association.
- **Notebook user** — creates an owner-scoped notebook and expects the exact
  stored record and captured items to open again.
- **Citation user** — copies or downloads Citation, BibTeX, RIS, CSL-JSON,
  Markdown, JSON, or a route link from the current reading frame.
- **Research exporter** — needs to distinguish browser-derived metadata and
  authored specimen exports from edition-pinned canonical citations and the
  server's customer-data export.
- **Studio researcher** — creates a rights-governed project, anchors an exact
  frame range, authors a Nisaba-native notebook/card, and exports the study
  trail without assuming it appears in the legacy notebook reader.

## Pre-conditions

- The customer is authenticated and has `domain:*` or `domain:nisaba` scope.
- The interactive workspace can read daily/passages, notebook summaries,
  annotations, grounded views, and manuscript evidence from `/v1/nisaba/*`.
- Production requires `nisaba-study-workspaces` durability. Notebook and
  annotation mutations are acknowledged only after the ordered snapshot save;
  missing persistence returns `503` and a post-erasure stale write returns
  `409`.
- `/nisaba/notebook` remains the Renata K. specimen from
  `getNisabaNotebookFixture()` even when an `id` query parameter is present.
- Browser notes under `oshun.nisaba.study-notes` and client citation output are
  separate from the durable notebook/annotation snapshot.
- `/studio/study` requires a valid Oshun session plus configured study-service
  URL/signing secret. The service enables business routes only with Postgres,
  object storage, and a media inbox; its notebook endpoints additionally require
  `NISABA_DATABASE_URL`.
- Its capability inventory now has four available entries: two links into the
  live study app plus Nisaba notebooks and Library. Ten craft lenses publish
  manual-annotation vocabularies without analyzers, and automated lens analysis
  is the one explicitly unavailable capability.
- The study service can hard-delete an owner-controlled project only after it is
  archived and its source list is empty. That project tombstone is not an
  account-erasure operation and does not cascade Nisaba notebook or card rows.
- The generated service client now supports grant correction, renewal,
  revocation, quarantine review, allowed-actions reads, and layered resolution.
  It also exposes non-mutating change simulation and chain-ordered rights-audit
  history. `StudyWorkspaceApp` still exposes only initial grant creation, so
  those follow-up operations are service evidence rather than a browser review
  flow.

## Steps

### 1. Choose the record authority before capture

- Use `/studio/study` for a rights-governed media project and a durable
  anchor-cited Nisaba notebook/card. This route is now interactive; it is not
  just a launchpad.
- Use the Nisaba domain workspace for the legacy corpus, BFF annotations,
  notebook summaries, local study notes, and six-format browser citations.
- Enter the Nisaba domain workspace at `/domains/nisaba` or a passage target
  such as `/library/passage/:passageId` through the shell route.
- The workspace reads the public-domain BFF corpus, selected passage, notebook
  summaries, annotations, grounded views, and source/manuscript data.
- Its `live | fallback | curated` marker identifies whether the browser has all
  expected BFF responses. Do not confuse this surface with the simpler `/nisaba`
  reading desk or the `/nisaba/notebook` specimen.

### 2. Author an anchored Studio notebook and study card

- Create a study project, register a local rights-cleared work, record the
  rights decision, ingest it, and create a manual frame-range or region anchor.
  The web proxy verifies the HttpOnly Oshun session and forwards a short-lived
  study token; no service credential reaches the browser.
- Enter a notebook title and narrative. The client requires at least one anchor,
  then always cites `trail.anchors[0]` with marker `^1`. Nisaba-owned code mints
  a `nbk_` ref and writes revision 1 to the `nisaba_study` database.
- Add a study-card insight. The client again cites the first anchor; Nisaba
  mints a `crd_` ref, stores the card, and supersedes the notebook to list it.
- Export the study trail. With the Nisaba adapter wired, the rights-filtered
  JSON includes the current notebook, lives in the object store, and is returned
  by a five-minute presigned URL.
- Keep the limits visible: the UI has no anchor/marker picker, notebook detail,
  or publication control. Notebook creation writes Nisaba before the Yemaya
  project ref, and card creation writes the card before the notebook revision;
  neither sequence is transactional or compensated on a later failure.
- Do not treat a known opaque ref as permission. The card route validates the
  supplied anchor's project but currently does not verify that the target
  notebook belongs to that project, tenant, or actor before mutation.

### 3. Create and list a durable legacy BFF notebook

- Open `/nisaba/notebook/new`, enter title, visibility, and optional text, then
  submit. The form sends bearer and CSRF headers to `POST /v1/nisaba/notebooks`.
- The optional field is labelled **First passage**, but its text becomes the
  notebook `summary`. The request sends no `linkedPassageId`, so creation does
  not capture a passage item.
- `GET /v1/nisaba/notebooks` returns only the caller's rows; PATCH can rename or
  change summary, visibility, tags, or status. Production awaits the durable
  snapshot before returning success.
- `/nisaba/notebooks` renders real rows and a real empty state. If an
  authenticated BFF read refuses, it silently renders three review fixtures.
- Both the index and create-success panel link to `/nisaba/notebook?id=<id>`.
  That page ignores the id. The BFF's real launch path is
  `/workspace/notebook/<id>`, which the domain workspace can hydrate as a
  selected notebook summary.

### 4. Select and annotate a passage

- The interactive workspace can derive a text selection and open the annotation
  inspector.
- Saving posts selection offsets/excerpt, note, color, visibility, tags,
  notebook ids, and evidence-view ids to
  `POST /v1/nisaba/passages/:passageId/annotations`.
- The BFF validates the caller-owned notebook and evidence references, creates
  the annotation, and materializes an `annotation` item in every associated
  notebook before durable acknowledgment.
- Update can change the note, styling, tags, associations, and status. Archive
  is a soft status change; it does not remove an associated notebook item while
  its notebook id remains attached.
- Current named browser cases seed a real annotation through HTTP and then
  update/archive it in the UI. They do not yet drive selection-based browser
  creation and notebook-item read-back as one test.

### 5. Save a browser study note

- The Notes inspector offers anchor/compare/evidence/lineage/notebook frames,
  title, body, and tags.
- **Save note** writes a `NisabaStudyNote` to `oshun.nisaba.study-notes`, keeps
  at most 24 notes, and emits text-safe browser telemetry.
- It does not POST the note to the BFF notebook, item, or annotation routes.
  **Saved to <notebook>** means the local record contains that notebook id.
- The interface also says **Durable notes stay attached ...**; current storage
  does not support that durability claim.

### 6. Exercise real notebook-item capture

- `POST /v1/nisaba/notebooks/:notebookId/items` accepts `passage`, `annotation`,
  `grounded-evidence-view`, or `compare` plus a resolvable `refId`.
- Passage capture is owner-scoped, duplicate capture is idempotent, and an
  unknown resource returns `404 nisaba_notebook_item_not_found` without a
  revision bump.
- Annotation association reaches the same notebook item model automatically. The
  current reading buttons do not call the dedicated item route for passage,
  grounded-evidence, or compare capture.

### 7. Generate citation formats in the workspace

- Open the Citations inspector for the selected passage, compare lane, concept,
  grounded view, manuscript, annotation, notebook summary, collection, study
  plan, or other current artifact.
- Choose among exactly: **Citation**, **BibTeX**, **RIS**, **CSL-JSON**,
  **Markdown**, and **JSON**.
- Copy the rendered text, copy the artifact link, download the selected format,
  or open the source artifact.
- The browser synthesizes these values from current artifact title, meta,
  summary, route, selected passage, and access date. It does not use a canonical
  citation id, edition version, DOI authority, source hash, or signed manifest.

### 8. Inspect source evidence

- The citation trail and source inspectors expose BFF-provided source titles,
  manuscript context, grounded status, and lineage relationships.
- The trail's verification state is derived from the source-lineage grounded
  view. The component source explicitly notes that the BFF does not yet ship
  canonical citation-trail data.
- That evidence helps a reader evaluate the selected passage, but the citation
  exporter does not pin output to evidence ids or enforce a stable retirement /
  replacement chain.

### 9. Inspect the notebook specimen and exports

- Open `/nisaba/notebook` with or without an `id` query.
- The header, **14 entries**, last-edit time, word count, citation density,
  pinned passages, retraction marker, and Lilith suggestion are authored fixture
  copy. **Cite this** and **Resolve** are inert.
- Its Export block works: it creates fixture-derived Markdown, BibTeX, a minimal
  PDF Blob, and invokes `window.print` for **Print specimen**.
- `robots: { index: false, follow: false }` emits `noindex,nofollow`. That is
  crawler guidance, not authorization or proof that the specimen is the caller's
  private stored notebook.

## Post-conditions

- A Studio researcher can author a durable Nisaba-native notebook and study card
  against a validated anchor, reopen the notebook list after an app restart, and
  include the notebook in a rights-filtered study-trail export.
- That Studio record remains separate from the legacy BFF notebook index,
  workspace summary, and specimen detail route.
- Source deletion removes study media/exports and opens review tasks for cited
  Studio notebooks; it does not erase those Nisaba-owned records. The account
  DSAR registry also does not yet enumerate or delete `nisaba_study` notebooks
  or cards by author.
- A caller can create/list/get/update a durable owner-scoped BFF notebook and
  capture a resolvable item through real HTTP.
- A caller can create/update/archive a durable BFF annotation, and a notebook
  association materializes a notebook item.
- Production refuses to acknowledge an unpersisted write; account deletion
  erases and fences notebooks/annotations, and customer export includes both
  record types.
- A workspace study note persists only in that browser's localStorage.
- Workspace citation formats can be copied and downloaded, but are
  metadata-derived rather than edition-pinned canonical citations.
- The `/nisaba/notebook` exports contain authored specimen data, not the stored
  notebook selected by `id`.

## Failure modes

- **“First passage” supplied during creation** — it becomes summary text; no
  passage id or item is captured.
- **BFF list read refuses** — the index silently shows three review fixtures
  instead of a labelled degraded state.
- **Stored notebook opened from the index** — the destination ignores its id and
  displays Renata K.'s fixture.
- **Studio service or Nisaba database missing** — the proxy/service returns an
  honest `503`; it does not substitute the legacy BFF store or a fixture.
- **Studio card appended to a known foreign notebook ref** — the current route
  checks the anchor's project but not the notebook's project, tenant, or author;
  this is an authorization gap, not a supported sharing path.
- **Second Studio write fails** — notebook creation and card append cross store
  boundaries without a transaction or compensation, so an orphan first write can
  remain.
- **Studio notebook expected in legacy pages** — no adapter hydrates `nbk_`
  records into `/nisaba/notebooks`, `/workspace/notebook/:id`, or the
  `/nisaba/notebook` specimen.
- **Account export/deletion expected to cover Studio records** — current BFF
  partitions cover the legacy snapshot only; `nisaba_study` notebooks/cards have
  no wired author-scoped DSAR path.
- **Durable sink missing or save fails** — the BFF returns
  `503 nisaba_study_workspace_persistence_unavailable` and leaves visible state
  unchanged.
- **Stale write after account erasure** — the BFF returns
  `409 nisaba_study_workspace_subject_deleted`.
- **Note says “Saved” or “Durable”** — only localStorage changed; another
  device, customer export, and the BFF do not receive it.
- **Annotation archived** — its notebook item remains while the notebook id is
  still associated.
- **Concurrent edit** — the store orders writes, but the API accepts no expected
  revision or `If-Match` precondition.
- **Citation treated as canonical** — exporter lacks edition pin, stable source
  authority, hash, and manifest.
- **Requested Chicago/APA/MLA/SBL format** — not present in the current format
  set.
- **Fixture `Cite this` or `Resolve` clicked** — no picker or mutation opens.
- **Hard-coded notebook metrics interpreted as live** — entry count, last edit,
  word count, density, and suggestion are authored values.
- **`noindex,nofollow` interpreted as access control** — it only instructs
  compliant crawlers.

## E2E coverage

- [`apps/oshun/web/e2e/nisaba-notebooks-index.spec.ts`](../../apps/oshun/web/e2e/nisaba-notebooks-index.spec.ts)
  contains seven cases for live, empty, fixture-fallback, mobile, standalone,
  service-worker replay, and anonymous-gate states.
- [`apps/oshun/web/e2e/nisaba-notebook-new.spec.ts`](../../apps/oshun/web/e2e/nisaba-notebook-new.spec.ts)
  contains two cases for authenticated creation/read-back, CSRF, radio keyboard
  behavior, text-safe telemetry, and mobile containment.
- [`apps/oshun/web/e2e/nisaba-annotation-bff.spec.ts`](../../apps/oshun/web/e2e/nisaba-annotation-bff.spec.ts)
  contains four real-HTTP cases for auth, scope, payload, and annotation
  lifecycle gates.
- [`apps/oshun/web/e2e/nisaba-notebook-bff.spec.ts`](../../apps/oshun/web/e2e/nisaba-notebook-bff.spec.ts)
  contains five real-HTTP cases for create/rename/get, passage capture,
  idempotency, unknown refs, payload, auth, and scope.
- [`apps/oshun/web/e2e/nisaba-split-view.spec.ts`](../../apps/oshun/web/e2e/nisaba-split-view.spec.ts)
  contains 18 live-workspace cases, including local note save, real annotation
  update/archive, notebook hydration, and citation controls.
- [`apps/oshun/web/e2e/nisaba-reading-compare-annotate.spec.ts`](../../apps/oshun/web/e2e/nisaba-reading-compare-annotate.spec.ts)
  contains five live reading/compare/annotation/citation cases.
- [`apps/oshun/web/e2e/nisaba-notebook-capture-cite.spec.ts`](../../apps/oshun/web/e2e/nisaba-notebook-capture-cite.spec.ts)
  contains six live-source, format, copy, specimen-download, print, and robots
  cases.
- [`apps/oshun/web/e2e/nisaba-analytics.spec.ts`](../../apps/oshun/web/e2e/nisaba-analytics.spec.ts)
  contains one local-note and text-safe analytics case against a real notebook
  id.
- [`apps/oshun/web/e2e/nisaba-metis-study-prompts.spec.ts`](../../apps/oshun/web/e2e/nisaba-metis-study-prompts.spec.ts)
  contains two source-context handoff cases into Metis.
- [`apps/oshun/web/src/app/studio/study/__tests__/study-page.spec.tsx`](../../apps/oshun/web/src/app/studio/study/__tests__/study-page.spec.tsx)
  adds six component cases for the three-state manual-first posture, ten
  manual-only lenses, the unavailable analyzer, real routes, and metadata.
- [`apps/oshun/web/e2e/studio-study-walking-skeleton.spec.ts`](../../apps/oshun/web/e2e/studio-study-walking-skeleton.spec.ts)
  contains three real-stack browser cases: honest launch/accessibility, the full
  notebook/card/export/delete journey, and rights-expiry retention.
- [`apps/oshun/web/e2e/studio-study-a11y.spec.ts`](../../apps/oshun/web/e2e/studio-study-a11y.spec.ts),
  [`apps/oshun/web/e2e/studio-study-alignment-maps.spec.ts`](../../apps/oshun/web/e2e/studio-study-alignment-maps.spec.ts),
  and
  [`apps/oshun/web/e2e/studio-study-epistemic-types.spec.ts`](../../apps/oshun/web/e2e/studio-study-epistemic-types.spec.ts)
  add one case each for keyboard/screen-reader completion, human-reviewed map
  authoring, and distinct epistemic records. Together the four Studio files add
  six browser cases.
- [`apps/yemaya/svc-study-workspace/src/__tests__/walking-skeleton.integration.spec.ts`](../../apps/yemaya/svc-study-workspace/src/__tests__/walking-skeleton.integration.spec.ts),
  [`libs/yemaya/study-workspace/src/use-cases/manage-study-project.ts`](../../libs/yemaya/study-workspace/src/use-cases/manage-study-project.ts),
  [`libs/nisaba/study-adapter/src/conformance.spec.ts`](../../libs/nisaba/study-adapter/src/conformance.spec.ts),
  and
  [`libs/yemaya/study-workspace/src/notebook-publication.spec.ts`](../../libs/yemaya/study-workspace/src/notebook-publication.spec.ts)
  cover real Postgres/MinIO/ffmpeg continuity, Nisaba identity/persistence
  seams, and rights-gated publication. The real-stack suite skips when its
  services are absent unless `STUDY_PG_REQUIRED=1`.
- [`apps/oshun/bff/src/nisaba/state-durability.test.ts`](../../apps/oshun/bff/src/nisaba/state-durability.test.ts),
  [`apps/oshun/bff/src/routes/nisaba-durability.test.ts`](../../apps/oshun/bff/src/routes/nisaba-durability.test.ts),
  and
  [`apps/oshun/bff/src/nisaba/state-durability.integration.test.ts`](../../apps/oshun/bff/src/nisaba/state-durability.integration.test.ts)
  add 13 store cases, two HTTP failure cases, and one environment-gated real-
  Postgres case.

## Per-view files touched

- [`customer/07-nisaba/nisaba.md`](../customer/07-nisaba/nisaba.md) — reading
  desk and domain workspace entry.
- [`customer/07-nisaba/nisaba-notebooks.md`](../customer/07-nisaba/nisaba-notebooks.md)
  — real list, empty, fixture-fallback, offline, and mobile states.
- [`customer/07-nisaba/nisaba-notebook-new.md`](../customer/07-nisaba/nisaba-notebook-new.md)
  — real create form and summary-versus-passage boundary.
- [`customer/07-nisaba/nisaba-notebook.md`](../customer/07-nisaba/nisaba-notebook.md)
  — id-ignoring fixture detail and exports.
- [`customer/07-nisaba/nisaba-scholar.md`](../customer/07-nisaba/nisaba-scholar.md),
  [`customer/07-nisaba/nisaba-manuscript.md`](../customer/07-nisaba/nisaba-manuscript.md),
  and
  [`customer/07-nisaba/nisaba-lexicon.md`](../customer/07-nisaba/nisaba-lexicon.md)
  — adjacent citation sources.

## Cross-references

- `apps/oshun/web/src/components/domains/NisabaSurface.tsx` — live workspace,
  local notes, annotations, and citation formats.
- `apps/oshun/web/src/components/studio/StudioStudyWorkspace.tsx` and
  `StudyWorkspaceApp.tsx` — honest available/manual-only/unavailable inventory
  plus the live study project, anchor, notebook/card, export, expiry, and
  deletion client.
- `apps/oshun/web/src/app/api/study/[...path]/route.ts` and
  `apps/yemaya/svc-study-workspace/src/routes/study-routes.ts` —
  verified-session proxy and the durable study-service contracts.
- `libs/nisaba/study-adapter/src/adapter.ts` and `notebook-store.ts` —
  Nisaba-native refs, revisioned Postgres records, and the current multi-store
  mutation boundaries.
- `apps/oshun/bff/src/routes/nisaba.ts` and `apps/oshun/bff/src/nisaba/state.ts`
  — durable notebook, item, annotation, passage, and evidence APIs.
- `apps/oshun/web/src/components/lilith/NisabaNotebookExportBlock.tsx` — fixture
  export generation.
- [`nisaba-scholarly-read.md`](./nisaba-scholarly-read.md) — broader reading
  workflow.
- [`citation-drift-resolution.md`](./citation-drift-resolution.md) — operator
  handling when evidence moves.
- [`account-deletion-and-dsar.md`](./account-deletion-and-dsar.md) — durable
  export/erasure authority.

## Open questions

- [ ] Make `/nisaba/notebook?id=` hydrate the requested server notebook and its
      items, or route every live link to `/workspace/notebook/:id`.
- [ ] Rename **First passage** to **Summary** or capture a resolvable linked
      passage/item.
- [ ] Replace silent index fixtures with a labelled degraded state and retry.
- [ ] Persist browser study notes through an exportable/erasable BFF note model
      and correct the current durable-sounding copy.
- [ ] Add a real browser selection-create-to-notebook-item-restart test.
- [ ] Define archive/detach/delete semantics for associated annotation items.
- [ ] Add optimistic revision/conflict semantics for notebooks and annotations.
- [ ] Define canonical citation ids, edition/version pins, locator granularity,
      hashes, manifests, and retirement/replacement behavior.
- [ ] Export the selected stored notebook and decide whether Chicago, APA, MLA,
      SBL, or CSL style rendering belongs in this surface.
- [ ] Replace or clearly label the specimen's authored metrics, Lilith
      suggestion, privacy copy, and inert controls.
