feat(05-03): freeze guidance_sessions envelope as types-only contract (GREEN)
- GuidanceSessionEnvelope: EXACTLY id, chat_id, route_snapshot, created_at (SessionClaim field-freeze law — a 5th property means drift) - GuidanceRouteSnapshot INLINE (D-07: one key, one TTL, ~2h): destination id/name, distanceM/durationS, polyline6 geometry (05-01 storage format), startedAtSec resume anchor - GUIDANCE_SESSION_TTL_SECONDS = 7200 — every Phase 6 write carries it - guidance:<id> key-scheme doc header; zero runtime behavior (no binding, no function, no import — GE4 pins it) Note: header says 'No KV binding' rather than naming the KV type because the acceptance gate requires that token to appear NOWHERE in the file, comments included — same law, gate-clean wording.
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* guidance-sessions.ts — the FROZEN Phase 6 contract, types-only (D-06/D-07).
|
||||
* ------------------------------------------------------------------------
|
||||
* THIS MODULE SHIPS NO BEHAVIOR. No KV binding, no Env field, no wrangler
|
||||
* namespace, no runtime function — the envelope is designed here (ROADMAP
|
||||
* §Phase 5 GUID-05/06 upstream obligation) so Phase 6 builds its service
|
||||
* on a frozen shape. Phase 6's service owns every write; every write
|
||||
* carries expirationTtl: GUIDANCE_SESSION_TTL_SECONDS (~2h) and the
|
||||
* snapshot is INLINE (one key, one TTL) — nothing outlives 2h, nothing is
|
||||
* reconstructable after expiry (D-07, the location-pin TTL precedent).
|
||||
*
|
||||
* Key scheme: guidance:<id> → JSON GuidanceSessionEnvelope
|
||||
*/
|
||||
|
||||
/** ~2h (D-06) — the envelope's every future write carries THIS value as its
|
||||
* expirationTtl (Phase 6's privacy grep gate extends the TTL-law to it). */
|
||||
export const GUIDANCE_SESSION_TTL_SECONDS = 7200;
|
||||
|
||||
/**
|
||||
* The route snapshot — INLINE in the envelope (D-07): one KV key, one TTL.
|
||||
* Nothing outlives 2h; nothing is reconstructable after expiry. Scoped to
|
||||
* what a chat turn-card needs (GUID-05): the selected route's headline data
|
||||
* + its geometry for the map snapshot render + the trip-start anchor for
|
||||
* progress math on resume (GUID-06).
|
||||
*/
|
||||
export interface GuidanceRouteSnapshot {
|
||||
/** The gazetteer id of the trip's destination. */
|
||||
destinationId: string;
|
||||
/** The destination's display name (verbatim gazetteer name). */
|
||||
destinationName: string;
|
||||
/** Selected route summary (meters / seconds). */
|
||||
distanceM: number;
|
||||
durationS: number;
|
||||
/** The SELECTED route's geometry, polyline6-encoded — the routing
|
||||
* workspace's storage format (05-01), never a re-serialized array. */
|
||||
geometry: string;
|
||||
/** Trip start, seconds-since-epoch — the resume-progress anchor (GUID-06). */
|
||||
startedAtSec: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* The guidance_sessions envelope — Phase 6's frozen contract (D-06).
|
||||
* EXACTLY these four fields: a 5th property means drift (the SessionClaim
|
||||
* law, bot/src/kv/sessions.ts).
|
||||
*
|
||||
* Key scheme: guidance:<id> → JSON GuidanceSessionEnvelope
|
||||
* Every write MUST carry expirationTtl: GUIDANCE_SESSION_TTL_SECONDS.
|
||||
*/
|
||||
export interface GuidanceSessionEnvelope {
|
||||
/** Opaque session id — crypto.randomUUID() at Phase 6 mint (T-02-05 precedent). */
|
||||
id: string;
|
||||
/** The Telegram chat the turn-cards push to (GUID-05). */
|
||||
chat_id: number;
|
||||
/** The INLINE route snapshot (D-07) — never a reference or a second key. */
|
||||
route_snapshot: GuidanceRouteSnapshot;
|
||||
/** Envelope creation, seconds-since-epoch. */
|
||||
created_at: number;
|
||||
}
|
||||
Reference in New Issue
Block a user