4.7 KiB
4.7 KiB
ROADMAP — Keysat
Longer-term backlog. Near-term state lives in AGENTS.md → Current state.
Payments & subscriptions
- Per-profile SMTP override (schema fields exist from the keysat-smtp-emails plan; needs the form + send path).
- Rail-preference editing UI — only matters when two providers on one profile both serve the same rail; settable today via
PUT /v1/admin/merchant-profiles/:id/rail-preferences/:rail. - Keysat-side dedup cache for Zaprite contacts (same buyer purchasing recurring twice can create duplicate Zaprite contacts).
- Zaprite declined-card / expired-profile failure-body shapes are undocumented — harden
try_auto_charge_zapriteonce observed in production.
Agent compatibility & scoped API keys
- Agent-delegable payment-provider connect (approved, not urgent — see
plans/agent-payment-connect-scope.md). Add an à-la-cartepayment_providers:writescope (never bundled intomerchant-onboard), gated by a daemon-level sandbox-mode flag as the outer gate (production daemons reject scoped connect entirely) with a network gate inner defense (regtest/testnet/signet only, fail-closed to mainnet). BTCPay network is derived from an on-chain address prefix (noserver/infofield exists). - Onboarding doc-harness — Stage 2 (Path 2, regtest buyer-pays). Gated on slices 3–5 above.
Stage 1 (Path 1, no payments) shipped
completed-cleanthis session — harness atlicensing-service-startos/onboarding-harness/, record in itsSTAGE1-RESULT.md. Stage 2 reuses the harness but boots the fixture withKEYSAT_SANDBOX_MODEon, stands up a Dockerized BTCPay regtest stack (bitcoind regtest + NBXplorer + Postgres + BTCPay) as additional disposable infra, and grants the agentmerchant-onboard+payment_providers:write. Goal: the agent connects BTCPay (regtest) over the API and drives a test buyer payment that activates a license, with zero master-key steps. The walkthrough must be explicitly labeled regtest/test-network and must state that connecting a real mainnet wallet is the one operator-reserved step by design (a key that can redirect funds stays with the human) — a security feature, not a gap.
Packaging & distribution
- Start9 Community Registry submission — criteria are unpublished; contact Start9 directly when ready.
Licensing model
- Evaluate Elastic License v2 vs the current custom
LicenseRef-Keysat-1.0(parked decision).
Validation
- Re-test
KEYSAT_INTEGRATION.mdagainst a fresh downstream app to confirm a clean one-shot SDK integration. - End-to-end Zaprite sandbox pass on the multi-merchant-profile webhook routing before relying on it in production.
Design (contract conformance)
The brand contract now lives in design/DESIGN.md + design/tokens.tokens.json (distilled
2026-06-16 from the prior Claude Design system, now archived in design/_imports/). A
design-checker audit (2026-06-16) found high fidelity overall, with these items where the
code contradicts the contract's stated rules or bypasses the token scale:
Blockers (code violates a named "never" rule):
- Gold used as an actionable fill (contract: gold is accent/border only, never a fill).
(a) admin SPA
.featured-pill-toggle.on→web/index.html:418; (b) admin sidebar upgrade CTA#tier-banner-cta→web/index.html:537-542. Fix to navy-fill or gold-border/text. - Primary buy CTA uses pill radius
999px(contract: buttons arer-md8px; pill is badges-only) —keysat-xyz-landing/index.html:384-385. Set to 8px.
Structural (headline):
- All four surfaces inline their own copy of the CSS variables instead of importing the
canonical
design/brand/palette.css(landing :33-56, registry :11-22, docs.css :7-21, admin :9-25). Copies are currently exact but one edit from drift. Consolidate ontopalette.css.
Token gaps / drift (decide: tokenize the as-built value, or snap to an existing token):
14pxcard radius used throughout the marketing landing — not a token (betweenr-lg12 andr-xl18). Snap to a token or add one.- Wordmark letter-spacing is
0.30em(landing) vs0.28em(docs/admin) and has no token — pick one value, add aletterSpacing.wordmarktoken. - Semantic badge text colors (
#205c47/#7a5814/#8a2828) are darker one-offs with no token — addsemantic.*-texttokens or reference existing ones. - Syntax-highlight colors hardcoded as hex (
#d4b985=gold-400,#a6b7cf=navy-300) — switch tovar(). One admin hex#f6f1e7isn't a token (closest cream-50/100) — reconcile. - Sticky-header backdrop on docs/admin (
blur(10px)/blur(8px)) diverges from the contract'sblur(12px)— align if a single header treatment is wanted.