V1 Web PWA · Walk result

Dependency result: Nyx logged-observation contract

A dated evidence record for V1 Web PWA: observed behavior, current source reconciliation, automation evidence, and explicit proof limits.

verdict: partial· date unknown
8sections4 minread1table

On this page
  • Opened: 2026-05-29 to distinguish a user’s observed event from the existing forecast-window contract and to record the missing canonical model.
  • Reconciled: 2026-07-18 against LoggedObservationSchema, persistence registration, generated Prisma, the shipped migration, the dual-write adapter, and its live-DB test. This was a source reconciliation, not a fresh production walk.
  • Verdict: partial — the canonical contract and initial persistence path now exist, so the old “missing model” decision is resolved. The adapter fills unavailable site and sky fields with neutral placeholders, maps free-text labels into event_type, reads the legacy table, and never validates the inserted projection through LoggedObservationSchema.
  • Primary spec: apps/oshun/bff/src/routes/domain-stubs-postgres.test.ts.

Result at a glance#

Evidence lane Current result Authority limit
Contract design User, event, site, sky, quality, equipment, attachments, sharing, source ship Does not model group observers; product decision is single userId
Persistence model Registry, Prisma model, migration, indexes, and tombstones ship Repository presence; production rollout not inspected
Creation write Observation creation inserts legacy and canonical rows Sequential inserts with no transaction or repair receipt
Initial mapping Conditions map to cloud cover and quality; unknown site is an explicit neutral 0,0, UTC, and unspecified are placeholders, not observed provenance
Automated evidence Live-DB test checks canonical row, condition projection, and web source client It does not parse the row or prove every condition/attachment/equipment
Read/corroboration Observation listing still reads the legacy row No canonical read, forecast match, attachment lifecycle, sharing, or delete

Evidence map#

The implemented projection closes the storage gap while leaving provenance and canonical authority unresolved.

flowchart LR A[Log observation form] --> B[Legacy observation row] B --> C[Project condition and neutral site] C --> D[v1_nyx_logged_observation] D -. reads still legacy .-> E[Observation journal] D -. no connected match .-> F[Observation window corroboration] D -. no connected flow .-> G[Attachments and public sharing] B -. no atomic rollback .-> H[Possible split write]

Proven observations#

Observation now has a distinct canonical type#

  • LoggedObservationSchema is separate from ObservationWindowSchema. It models what one user reports seeing, when and where, with sky conditions, quality, equipment, attachments, visibility, share scope, source client, and timestamps.
  • The persistence registry registers the contract and the generated schema maps it to v1_nyx_logged_observation. Migration 20260528022916_nyx_logged_observation_and_library_collection creates the table plus canonical identity, tenant, payload, live-scan, and tombstone indexes.
  • These artifacts retire the old instruction to design and register a new Nyx contract; they do not, by themselves, make it read authority.

Creation writes a deliberately sparse projection#

  • observations.add() stores the submitted event id, label, time, conditions, note, and owner in the legacy row, then constructs a canonical peer. Clear, partial, and overcast conditions map to cloud-cover estimates and quality bands; attachments and equipment start empty or null; sharing starts private.
  • Because the form does not collect a site, the canonical row uses latitude and longitude zero, elevation zero, UTC, and region unspecified. Those values communicate missing context only if consumers treat them as placeholders.
  • The live-DB test proves a clear observation produces a canonical row with zero-percent cloud cover, good quality, and web-app source.

Boundaries and gaps#

  • A placeholder site is not observation provenance. Coordinates 0,0 are a real place on Earth as well as a common sentinel. Without an explicit unknown flag, downstream geographic analysis could mistake missing context for Gulf of Guinea evidence.
  • Free text is not a valid event taxonomy. The adapter inserts targetLabel into event_type, while the contract expects SkyEventTypeSchema. The focused test uses “Perseid meteor shower peak” and never proves that reconstructed data passes the enum.
  • A canonical table row is not a contract-valid object. Adapter-generated ids and owner/event ids can be non-UUID while the Zod contract requires UUIDs; SQL column assertions do not detect that mismatch.
  • A dual-write is not atomic. Legacy and canonical inserts are separate queries with no transaction, outbox, or automated reconciliation path.
  • A write projection is not canonical read authority. The journal list still reads goal3_stub_observation, and there is no canonical update, attachment, share-scope, tombstone, or forecast-corroboration path.
  • Contract source is not production deployment proof. No production migration ledger, real observation row, or downstream forecast consumer was inspected in this reconciliation.

Re-run evidence#

Run the focused live-DB assertion with the repository Postgres test setup:

bash
pnpm exec vitest run \
  apps/oshun/bff/src/routes/domain-stubs-postgres.test.ts \
  -t "observations.add\(\) dual-writes"

A green result proves one initial condition mapping and canonical insert. It must not be summarized as contract validation, trustworthy geolocation, canonical journal reads, or observation-window corroboration.

Source trail#

Cross-references#

Open questions#

  • How will missing site be represented without overloading valid coordinates, and when will the product collect location, timezone, and consent?
  • What explicit mapping converts form target labels and optional object ids into SkyEventTypeSchema plus catalog identity?
  • Which boundary reconstructs the stored row and requires LoggedObservationSchema.parse before it is accepted as canonical?
  • Will the paired writes become transactional or outbox-backed, and what reconciliation detects historical split rows?
  • Which service owns canonical reads, attachments, forecast corroboration, privacy changes, and deletion/tombstone behavior?