anthodev/lapin-futepublic Fork
⑂ develop
Commits
⬇ Clone ▾
git clone https://git.rickub.com/anthodev/lapin-fute.git
git clone ssh://git@rickub.com/anthodev/lapin-fute.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

Download ZIP

[feature] Build the companion configuration page #5

Closed@github-anthodev opened this issue Aug 29, 2026
  • @github-anthodev opened this issue · Aug 29, 2026

    🔢 Impact Version (SemVer)

    MINOR


    🌿 Suggested Branch

    feature/phone-configuration/configuration/5


    📝 Description

    Build the small responsive page opened by Pebble's companion app so a user can enter/replace/remove a personal PRIM key, search valid places, choose only backend-offered line/direction services, preview, and atomically propose one complete configuration. Users never see transport identifiers or their previously stored key.

    The page must support French/English copy, preserve unsaved edits through recoverable failures, keep the stored secret out of the page/server, and meet a measured narrow-phone performance budget.


    ✅ Expected Behavior

    Inside the real companion webview, options show only whether a key is configured, offer a masked change/removal control, and edit the complete favorite list. The page returns ApiKeyUpdate plus favorites; unchanged secrets never re-enter the webview. French locales show French copy, all others English, and the narrow page remains responsive.


    📋 Acceptance Criteria

    • Select a small configuration-page stack compatible with supported companion webviews; do not add a native app or stock Clay auto-handler that reopens/pushes every setting.
    • Open with favorites plus hasKey in an encoded URL fragment never sent to the host; include no stored key. Never put configuration in path/query, HTML, generated JavaScript, or server-visible request data.
    • Add a masked key field (type=password, autocomplete=off, autocorrect/capitalization/spellcheck disabled), “replace” and explicit “remove” actions, bilingual explanation of phone-local plaintext storage, and a link to PRIM token creation.
    • Return the phone-only ApiKeyUpdate: KEEP by default, REPLACE with value only when the user typed a new key, or REMOVE. The key may transit only the documented one-time encoded configuration-close fragment, which is never sent to the HTTP server; do not log the close response.
    • Accept a non-empty replacement key within the foundation-frozen UTF-8 byte bound as opaque input; do not infer token syntax or call live stop-monitoring here. The first composed departure event in [feature] Deliver Pebble watch consultation (https://github.com/Anthodev/lapin-fute/issues/7) owns authoritative miss-time 401/403.
    • Implement stop/station → valid line → valid direction → preview → save using only backend combinations. Debounce search by 300 ms, require 2 characters, cancel superseded requests, and render at most 20 results; catalog search never spends PRIM quota.
    • Create three favorites without exposing any raw identifier; implement rename/reorder/delete and return the expected ordered list.
    • Preserve unsaved key/favorite state through recoverable errors. On cancel, empty/oversized replacement key, backend failure, or failed favorite validation, return no replacement and preserve the prior phone configuration.
    • Cover missing/configured/replacement/removal key presentation plus empty/loading/no-result/invalid-service/backend-unavailable favorite states.
    • On a narrow mobile profile, require compressed first-load JS+CSS ≤200 KiB, LCP ≤2.5 s, INP ≤200 ms, and CLS ≤0.1 in a recorded synthetic run; add no telemetry/RUM.
    • The complete flow works inside the real companion app in both languages without the key appearing in page/server/console/network logs.
    • Record real-webview captures, key enter/replace/remove flows, three-favorite editing, cancel/failure preservation, bundle/Web-Vitals output, and redacted page/server/console proof in a resolution comment.

    🔗 Affected Endpoints/Routes

    • Consume bounded catalog routes without a key and recorded departure fixtures for preview; do not make live departure normalization a dependency.
    • Own the HTTPS configuration path/static assets and exact hasKey input plus ApiKeyUpdate close-response contract consumed by [feature] Persist and synchronize favorites (https://github.com/Anthodev/lapin-fute/issues/6).

    🧪 Tests to Add

    Type Coverage
    UI/component tests Masked key state/actions, bounded opaque input, debounced search, valid combinations/fixture preview, editing, complete-save payload
    Secret/state tests `KEEP
    Localization tests French, English/default, fallback, unchanged user/backend labels, key-state/error copy
    Performance/webview smoke ≤200 KiB compressed JS+CSS; LCP/INP/CLS budgets; narrow real-companion flow in both locales

    ⚙️ Constraints

    • The page proposes one whole configuration; PebbleKit JS is the only persistence owner.
    • A saved favorite is one backend-validated service; never construct unrelated stop/line/direction values.
    • The key exists in page memory only while newly entered and in the encoded close fragment only on REPLACE; fragments are the documented unavoidable handoff and are never HTTP requests.
    • The page never receives the existing key. No key in query parameters, server logs, analytics, error reports, DOM serialization, or screenshots.
    • Use explicit HTML text assignment/escaping and a same-origin HTTPS/CSP policy; no telemetry, accounts, nearby stops, journey planning, or native app.

    🔀 Dependencies

    • Blocked by [feature] Resolve valid IDFM services (https://github.com/Anthodev/lapin-fute/issues/3). Consume its frozen route and opaque service-option contracts.
    • Reuse the shared Favorite contract from [feature] Establish the application foundation and contracts (https://github.com/Anthodev/lapin-fute/issues/2).

    ⚠️ Impact on Existing Behavior

    Introduces the user-facing configuration surface. It returns a candidate replacement only; [feature] Persist and synchronize favorites (https://github.com/Anthodev/lapin-fute/issues/6) remains the sole owner of durable storage and watch synchronization.


    🔍 Technical Context

    PebbleKit JS opens the page with favorites plus hasKey; the page returns only changed credential intent. A configuration close fragment is the documented companion channel and is accepted as one-time transient exposure, never a server request. Avoid Clay's automatic settings reopen/watch push for the secret.

    Required references

Sign in to comment.