From 040abb268006578eb51608468040bb1ee4a69f46 Mon Sep 17 00:00:00 2001 From: abrcrmb Date: Thu, 8 Oct 2026 19:32:22 +0100 Subject: [PATCH] chore(roadmap): sync this repo's copy with the reconciled canonical roadmap Run of scripts/roadmap-merge (F-15) in Kinlock-Org/.github on 2026-10-08. Copies are meant to be identical apart from ADR link paths, which differ because this file sits at the repo root. Readiness recomputed by scripts/roadmap-progress: 74 of 204 rows DONE, 41%. --- ROADMAP.md | 162 ++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 118 insertions(+), 44 deletions(-) diff --git a/ROADMAP.md b/ROADMAP.md index 9466f40..c7ed39f 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -4,7 +4,7 @@ | | | |---|---| -| **Last updated** | 2026-10-08 (M3-24: country-agnostic CI guard) | +| **Last updated** | 2026-10-08 (all copies reconciled with `scripts/roadmap-merge`; readiness 41%) | | **Docs baseline** | v0.3, worldwide scope (`PRD.md`, `ARCHITECTURE.md`, `ARCHITECTURE_ESSENTIALS.md`, `AGENTS.md`, `CLAUDE.md`, `project_structure.md`) | | **Current phase** | Phase 0 (Foundations) → starting Phase 1 (M0 Validate) | | **Readiness** | See [§3](#3-progress-snapshot) | @@ -127,19 +127,19 @@ Readiness % = `DONE ÷ (all rows − DEFERRED − DROPPED)`. Conditional rows (P | Phase | Total | DONE | IN PROGRESS | TODO | BLOCKED | DEFERRED | DROPPED | Readiness | |---|---|---|---|---|---|---|---|---| -| 0 Foundations | 19 | 12 | 2 | 5 | 0 | 0 | 0 | 63% | -| 1 M0 Validate | 17 | 0 | 1 | 16 | 0 | 0 | 0 | 0% | -| 2 Contract + registry | 36 | 16 | 5 | 15 | 0 | 0 | 0 | 44% | -| 3 SDK + indexer | 19 | 1 | 1 | 17 | 0 | 0 | 0 | 5% | -| 4 App | 26 | 15 | 5 | 6 | 0 | 0 | 0 | 58% | +| 0 Foundations | 19 | 16 | 1 | 2 | 0 | 0 | 0 | 84% | +| 1 M0 Validate | 17 | 1 | 6 | 10 | 0 | 0 | 0 | 6% | +| 2 Contract + registry | 37 | 24 | 3 | 10 | 0 | 0 | 0 | 65% | +| 3 SDK + indexer | 19 | 14 | 3 | 2 | 0 | 0 | 0 | 74% | +| 4 App | 26 | 15 | 7 | 4 | 0 | 0 | 0 | 58% | | 5 Testnet pilot | 7 | 0 | 0 | 7 | 0 | 0 | 0 | 0% | | 6 Pre-mainnet features | 10 | 0 | 0 | 10 | 0 | 0 | 0 | 0% | | 7 Hardening | 26 | 0 | 0 | 26 | 0 | 0 | 0 | 0% | | 8 Launch | 8 | 0 | 0 | 8 | 0 | 0 | 0 | 0% | | 9 Conditional ramp | 9 | 0 | 0 | 0 | 0 | 9 | 0 | n/a | -| 10 Wave + community | 8 | 1 | 0 | 7 | 0 | 0 | 0 | 13% | +| 10 Wave + community | 10 | 4 | 1 | 5 | 0 | 0 | 0 | 40% | | 11 Deferred parking lot | 16 | 0 | 0 | 0 | 0 | 16 | 0 | n/a | -| **All** | **201** | **45** | **14** | **117** | **0** | **25** | **0** | **26%** | +| **All** | **204** | **74** | **21** | **84** | **0** | **25** | **0** | **41%** | --- @@ -160,12 +160,12 @@ Readiness % = `DONE ÷ (all rows − DEFERRED − DROPPED)`. Conditional rows (P | F-08 | Confirm org name availability and create the GitHub org (`kinlock` or backup) | org | P0 | DONE | — | Org exists; owners set | | F-09 | Create org `.github` repo: profile README, CoC, CONTRIBUTING, SECURITY, SUPPORT, canonical `docs/`, `templates/` | org | P0 | IN PROGRESS | F-08 | Repo public; docs and templates committed | | F-10 | Decide license (org-wide) | org | P0 | DONE | F-08 | ADR written; `LICENSE` template ready | -| F-11 | Decide npm scope and publish rights | org | P0 | IN PROGRESS | F-08 | Scope reserved; publish tokens/process documented | -| F-12 | Create GitHub teams: maintainers, contract-reviewers, attesters | org | P0 | TODO | F-08 | Teams exist; handles match `CODEOWNERS` | -| F-13 | Create label set across repos (`security-sensitive`, `good first issue`, `wave`, `area:*`, `blocked:m0`, `deferred`) | org | P0 | TODO | F-08 | Labels applied via script | +| F-11 | Decide package names and distribution | org | P0 | DONE | F-08 | Package names chosen; release process documented and a release installs (ADR-0026) | +| F-12 | Create GitHub teams: maintainers, contract-reviewers, attesters | org | P0 | DONE | F-08 | Teams exist; handles match `CODEOWNERS` | +| F-13 | Create label set across repos (`security-sensitive`, `good first issue`, `wave`, `area:*`, `blocked:m0`, `deferred`) | org | P0 | DONE | F-08 | Labels applied via script | | F-14 | Write `scripts/sync-docs` and the `docs-in-sync` CI job | org | P0 | DONE | F-09 | CI fails when a vendored copy drifts | | F-15 | Write `roadmap-check` CI job and `scripts/roadmap-progress` and `scripts/roadmap-merge` | org | P0 | DONE | F-09 | CI fails PRs without roadmap update; scripts produce correct counts and merges | -| F-16 | Define branch protection and repo settings (required reviews, required checks, no force-push to `main`) | org | P0 | TODO | F-12 | Applied to all repos; documented | +| F-16 | Define branch protection and repo settings (required reviews, required checks, no force-push to `main`) | org | P0 | DONE | F-12 | Applied to all repos; documented | | F-17 | Create PR template and issue templates (bug, feature, wave-task) with Roadmap section | org | P0 | DONE | F-09 | Templates live in org `.github` and each repo | | F-18 | Cross-doc consistency review after any M0-driven change | org | P1 | TODO | M0-12 | All docs agree; ADR index current | | F-19 | Reconcile docs with scaffold findings: Next.js 16 renamed `middleware.ts` to `proxy.ts`; contract `tests/` must live in `contracts/kinlock/tests/` (a virtual Cargo workspace root can't hold integration tests); GitHub org is `Kinlock-Org`, not `kinlock`; request-link helpers are not in the SDK public API list; `TrancheInput` type added for `create_lock`; accept ADR-0017 and add it to the ADR indexes | org | P1 | TODO | — | Docs and scaffold agree; ADR-0017 accepted or rejected | @@ -180,20 +180,20 @@ Readiness % = `DONE ÷ (all rows − DEFERRED − DROPPED)`. Conditional rows (P | ID | Task | Repo | Pri | Status | Depends on | Done when | |---|---|---|---|---|---|---| -| M0-01 | Interview 15 senders across at least 2 candidate markets (script + note template) | org | P0 | TODO | F-08 | Notes stored; themes summarized; willingness to use USDC recorded | -| M0-02 | Interview 5 payees (schools, landlords) in candidate markets, incl. willingness to operate a wallet | org | P0 | TODO | F-08 | At least 3 of 5 answers recorded against the §8.2 trigger | -| M0-03 | Talk to at least 2 attesters (associations, NGOs) about accountability and process | org | P0 | TODO | F-08 | Named willing attesters or a documented "no" | -| M0-04 | Build sender all-in cost model vs incumbent routes | org | P0 | TODO | M0-01 | Spreadsheet with fees at each hop; target cost set (`M0-13`) | +| M0-01 | Interview 15 senders across at least 2 candidate markets (script + note template) | org | P0 | IN PROGRESS | F-08 | Notes stored; themes summarized; willingness to use USDC recorded | +| M0-02 | Interview 5 payees (schools, landlords) in candidate markets, incl. willingness to operate a wallet | org | P0 | IN PROGRESS | F-08 | At least 3 of 5 answers recorded against the §8.2 trigger | +| M0-03 | Talk to at least 2 attesters (associations, NGOs) about accountability and process | org | P0 | IN PROGRESS | F-08 | Named willing attesters or a documented "no" | +| M0-04 | Build sender all-in cost model vs incumbent routes | org | P0 | IN PROGRESS | M0-01 | Spreadsheet with fees at each hop; target cost set (`M0-13`) | | M0-05 | Off-ramp spike **per candidate market**: identify local-currency anchors and wallet routes (or whether payees can simply hold USDC); test SEP-1/10/24 on testnet; record assets, minimums, fees | org | P0 | TODO | — | Table of viable routes or a documented "none" | | M0-06 | Payee usability test: onboard 3–5 payees on testnet using the attester checklist | org | P0 | TODO | M0-02 | Task completion rates and pain points recorded | | M0-07 | Counsel intro call; written scoping of legal questions **per candidate market** (stablecoin acceptance by domestic payees, money transmission, sanctions and restricted jurisdictions, data protection including where senders live, terms) | org | P0 | TODO | — | Counsel engaged; question list and timeline agreed | | M0-08 | Verify network facts: max entry TTL, RPC event retention, SAC/trustline failure behavior, USDC issuer flags (freeze, authorization, clawback) | contracts | P0 | IN PROGRESS | — | Findings written; `MAX_LOCK_DURATION` confirmed or changed via ADR | | M0-09 | Research archive/backfill options for receipt verification (tier 3) and indexer gap recovery | sdk | P0 | TODO | M0-08 | Option chosen and costed; ADR drafted | -| M0-10 | Review Drips Wave rules: application limits, KYC, issue-sizing guidelines | org | P1 | TODO | — | Short note; Wave plan (`W-01`) adjusted | +| M0-10 | Review Drips Wave rules: application limits, KYC, issue-sizing guidelines | org | P1 | DONE | — | Short note; Wave plan (`W-01`) adjusted | | M0-11 | Write M0 findings report and go / pivot / stop decision against `PRD.md` §8.2 | org | P0 | TODO | M0-01..M0-09 | Report committed; decision recorded in §10 | | M0-12 | Revise PRD, architecture, essentials, and this roadmap per findings | org | P0 | TODO | M0-11 | Docs updated; changed rows noted in Changelog | | M0-13 | Set sender all-in cost target and pilot metric thresholds | org | P0 | TODO | M0-04 | Numbers recorded in PRD §8.1 | -| M0-14 | Competitive note: BarakahPay and other purpose-bound remittance projects | org | P1 | TODO | — | One-page comparison; differentiation confirmed or revised | +| M0-14 | Competitive note: BarakahPay and other purpose-bound remittance projects | org | P1 | IN PROGRESS | — | One-page comparison; differentiation confirmed or revised | | M0-15 | Decide a sustainability/revenue approach (grants, referral, B2B SDK, fee later) | org | P1 | TODO | M0-11 | ADR or PRD §13 answer recorded | | M0-16 | Choose pilot market(s) and write market-selection criteria (legal feasibility, attester supply, cash-out route, rate source, sender demand). Candidate: Nigeria plus at least one market in a different region and currency | org | P0 | TODO | M0-01, M0-02, M0-03 | Markets chosen and recorded (`DEC-19`) | | M0-17 | Define the supported-countries policy and restricted-jurisdiction approach with counsel (who decides, criteria, how the list changes) | org | P0 | TODO | M0-07 | Policy written; `DEC-20` resolved | @@ -210,7 +210,7 @@ Readiness % = `DONE ÷ (all rows − DEFERRED − DROPPED)`. Conditional rows (P | ID | Task | Repo | Pri | Status | Depends on | Done when | |---|---|---|---|---|---|---| -| M1-01 | Scaffold workspace: Cargo workspace, `rust-toolchain.toml`, empty modules, CI (fmt, clippy, test, build), `localnet.sh` | contracts | P0 | IN PROGRESS | G1 | CI green on empty skeleton; one-command local network | +| M1-01 | Scaffold workspace: Cargo workspace, `rust-toolchain.toml`, empty modules, CI (fmt, clippy, test, build), `localnet.sh` | contracts | P0 | DONE | G1 | CI green on empty skeleton; one-command local network | | M1-02 | Implement `constants.rs`, `types.rs`, `errors.rs`, `events.rs`, `storage.rs` | contracts | P0 | IN PROGRESS | M1-01 | Match `ARCHITECTURE.md` §4; enums append-only; events carry `schema_version` | | M1-03 | Admin functions: `init`, attester add/remove, token add/remove, `set_paused_new_locks`, `set_caps`, `upgrade` | contracts | P0 | DONE | M1-02 | Auth tested; pause blocks only `create_lock` | | M1-04 | Registry: `register_payee`, `set_status`, `update_payout` | contracts | P0 | DONE | M1-02 | Status transitions enforced; payout update affects new locks only | @@ -227,10 +227,10 @@ Readiness % = `DONE ÷ (all rows − DEFERRED − DROPPED)`. Conditional rows (P | M1-15 | Integration tests: C-address sender and payee, missing/unauthorized trustline, partial release then refund/decline, allowlist removal with open locks | contracts | P0 | TODO | M1-11 | Pass on local network | | M1-16 | Budget tests with `soroban-budget-assert`; compare local estimates to testnet simulation | contracts | P0 | TODO | M1-11 | Budgets recorded; divergence measured and documented | | M1-17 | `deploy.sh` (testnet default, mainnet guarded), `deployments/testnet.json`, generated `DEPLOYMENTS.md` | contracts | P0 | DONE | M1-11 | Deploys to testnet; mainnet requires flag and confirmation | -| M1-18 | Generate TS bindings and publish pipeline | contracts | P0 | TODO | M1-17, F-11 | Package published on tag; SDK can consume | +| M1-18 | Generate TS bindings and publish pipeline | contracts | P0 | DONE | M1-17, F-11 | Package published on tag; SDK can consume | | M1-19 | Deploy to testnet with a test multisig admin; add test attesters and testnet USDC | contracts | P0 | DONE | M1-17 | Contract ID recorded in `DEPLOYMENTS.md` | | M1-20 | Upgrade/migration test against a snapshot of testnet state | contracts | P1 | TODO | M1-19 | Invariants hold after upgrade | -| M1-21 | Contract `README`, `SECURITY.md`, and threat-model doc linked to invariants | contracts | P1 | TODO | M1-14 | Reviewer can map each threat to a control | +| M1-21 | Contract `README`, `SECURITY.md`, and threat-model doc linked to invariants | contracts | P1 | DONE | M1-14 | Reviewer can map each threat to a control | | M1-22 | Internal review using the `CLAUDE.md` contract checklist; fix findings | contracts | P0 | TODO | M1-16 | Checklist completed with evidence | | M1-23 | Decide optional `refund_to` (ADR) | contracts | P2 | TODO | M1-05 | ADR accepted or declined | | M1-30 | Source `soroban-budget-assert` (not published on crates.io) or choose an alternative for budget tests | contracts | P0 | TODO | — | Crate usable from CI; `M1-16` can start | @@ -240,17 +240,18 @@ Readiness % = `DONE ÷ (all rows − DEFERRED − DROPPED)`. Conditional rows (P | M1-34 | Decide `bump_lock` behavior when the full TTL no longer fits (clamp vs error) and after `expires_at + TTL_GRACE`; decide whether to convert seconds to ledgers more conservatively than 5 s | contracts | P1 | TODO | M1-33 | Decision recorded; tests cover it | | M1-35 | Spec decisions from the vault review: tranches with `unlock_at == expires_at` can never be released; suspend/re-activate toggling restarts the sender's refund grace | contracts | P1 | TODO | — | ADR accepted; code and tests follow it | | M1-36 | Failed token transfers surface the token's error code, which collides with Kinlock codes (SAC code 10 decodes as `PayeeAlreadyExists`); decide on a dedicated error or document it for the SDK | contracts | P1 | TODO | — | Decision recorded; SDK handles it | +| M1-37 | Script the local-network setup (identities, local USDC, contract, attester, token, one payee) so anyone can run the SDK smoke test locally | contracts | P1 | DONE | M2-02 | One command on a fresh local network prints the env block; the SDK smoke test passes with it | ### 6.2 `kinlock-registry` | ID | Task | Repo | Pri | Status | Depends on | Done when | |---|---|---|---|---|---|---| -| M1-24 | Scaffold registry: schema, `hash`, `validate` scripts, CI | registry | P0 | IN PROGRESS | G1 | CI validates schema and canonical formatting | -| M1-25 | `check-onchain` script and `onchain-match` workflow | registry | P0 | TODO | M1-19, M1-24 | Detects hash mismatch against testnet | -| M1-26 | Write `ATTESTER_CHECKLIST.md` and a script for trustline, XLM float, test release | registry | P0 | TODO | M0-06 | Checklist runs end to end on testnet | -| M1-27 | Add testnet fixture payees | registry | P0 | TODO | M1-24 | At least 3 examples across at least 2 countries, no personal data | +| M1-24 | Scaffold registry: schema, `hash`, `validate` scripts, CI | registry | P0 | DONE | G1 | CI validates schema and canonical formatting | +| M1-25 | `check-onchain` script and `onchain-match` workflow | registry | P0 | DONE | M1-19, M1-24 | Detects hash mismatch against testnet | +| M1-26 | Write `ATTESTER_CHECKLIST.md` and a script for trustline, XLM float, test release | registry | P0 | IN PROGRESS | M0-06 | Checklist runs end to end on testnet | +| M1-27 | Add testnet fixture payees | registry | P0 | DONE | M1-24 | At least 3 examples across at least 2 countries, no personal data | | M1-28 | `CODEOWNERS` for attesters | registry | P0 | TODO | F-12 | Attester review enforced | -| M1-29 | Registry: add `country` (ISO 3166-1), `local_currency` (ISO 4217), per-country directories, `supported-countries.json`, `attesters/.json`, and CI rules (supported country, attester scope, directory match, unique slug) | registry | P0 | IN PROGRESS | M0-16, M1-24 | Each rule has a failing-case test; fixtures cover at least 2 countries | +| M1-29 | Registry: add `country` (ISO 3166-1), `local_currency` (ISO 4217), per-country directories, `supported-countries.json`, `attesters/.json`, and CI rules (supported country, attester scope, directory match, unique slug) | registry | P0 | DONE | M0-16, M1-24 | Each rule has a failing-case test; fixtures cover at least 2 countries | --- @@ -262,24 +263,24 @@ Readiness % = `DONE ÷ (all rows − DEFERRED − DROPPED)`. Conditional rows (P | ID | Task | Repo | Pri | Status | Depends on | Done when | |---|---|---|---|---|---|---| | M2-01 | Scaffold `kinlock-sdk`: pnpm workspace, tsconfig, lint, CI, Postgres `docker-compose` | sdk | P0 | DONE | G1 | CI green on skeleton | -| M2-02 | SDK `client`: `createLock`, `release`, `refund`, `decline`, `getLock` (chain reads) | sdk | P0 | TODO | M1-18 | Works against local and testnet | -| M2-03 | SDK `hash` and `links`: `ref_hash`, `buildClaimLink`, `parseClaimLink`, request links | sdk | P0 | TODO | M2-02 | Fragment never leaves the client; round-trip tests | -| M2-04 | SDK `format`: bigint ↔ decimal strings; 7-decimal USDC formatting | sdk | P0 | TODO | M2-01 | No `number` used for money; edge-case tests | -| M2-05 | SDK `preflight`: balance, payee Active, recent payout change, duplicate `ref_hash`, authorized trustline | sdk | P0 | TODO | M2-02 | Each check has a test | -| M2-06 | SDK `receipts`: `verifyReceipt` tiers 1 and 2 | sdk | P0 | TODO | M2-02 | Valid and tampered receipts distinguished | -| M2-07 | SDK tests, including a check that nothing derived from the fragment is logged | sdk | P0 | TODO | M2-03 | Test fails if fragment data reaches logger | -| M2-08 | Indexer scaffold: Zod config, RPC client with multi-provider failover | sdk | P0 | TODO | M2-01 | Failover tested | -| M2-09 | Indexer ingest: poller, persisted cursor, gap detection | sdk | P0 | TODO | M2-08 | Gaps stop ingestion and alert; never skipped silently | -| M2-10 | Indexer handlers per event type and `schema_version` | sdk | P0 | TODO | M2-09, M1-02 | Mixed-version fixtures handled | -| M2-11 | DB schema and forward-only Drizzle migrations | sdk | P0 | IN PROGRESS | M2-01 | `chain_events`, `indexer_cursor`, `locks`, `tranches`, `payees` created | -| M2-12 | List API: `/locks`, `/locks/:id`, `/payees`, `/health` with lag | sdk | P0 | TODO | M2-10, M2-11 | OpenAPI or typed docs; lag exposed | -| M2-13 | Join payee display data from the registry repo | sdk | P0 | TODO | M1-25 | Payees show name, city, attester | -| M2-14 | Indexer tests: fixture replay, idempotency, cursor recovery, mixed versions | sdk | P0 | TODO | M2-10 | Replay twice yields identical DB | +| M2-02 | SDK `client`: `createLock`, `release`, `refund`, `decline`, `getLock` (chain reads) | sdk | P0 | DONE | M1-18 | Works against local and testnet | +| M2-03 | SDK `hash` and `links`: `ref_hash`, `buildClaimLink`, `parseClaimLink`, request links | sdk | P0 | DONE | M2-02 | Fragment never leaves the client; round-trip tests | +| M2-04 | SDK `format`: bigint ↔ decimal strings; 7-decimal USDC formatting | sdk | P0 | DONE | M2-01 | No `number` used for money; edge-case tests | +| M2-05 | SDK `preflight`: balance, payee Active, recent payout change, duplicate `ref_hash`, authorized trustline | sdk | P0 | DONE | M2-02 | Each check has a test | +| M2-06 | SDK `receipts`: `verifyReceipt` tiers 1 and 2 | sdk | P0 | DONE | M2-02 | Valid and tampered receipts distinguished | +| M2-07 | SDK tests, including a check that nothing derived from the fragment is logged | sdk | P0 | DONE | M2-03 | Test fails if fragment data reaches logger | +| M2-08 | Indexer scaffold: Zod config, RPC client with multi-provider failover | sdk | P0 | DONE | M2-01 | Failover tested | +| M2-09 | Indexer ingest: poller, persisted cursor, gap detection | sdk | P0 | DONE | M2-08 | Gaps stop ingestion and alert; never skipped silently | +| M2-10 | Indexer handlers per event type and `schema_version` | sdk | P0 | IN PROGRESS | M2-09, M1-02 | Mixed-version fixtures handled | +| M2-11 | DB schema and forward-only Drizzle migrations | sdk | P0 | DONE | M2-01 | `chain_events`, `indexer_cursor`, `locks`, `tranches`, `payees` created | +| M2-12 | List API: `/locks`, `/locks/:id`, `/payees`, `/health` with lag | sdk | P0 | DONE | M2-10, M2-11 | OpenAPI or typed docs; lag exposed | +| M2-13 | Join payee display data from the registry repo | sdk | P0 | DONE | M1-25 | Payees show name, city, attester | +| M2-14 | Indexer tests: fixture replay, idempotency, cursor recovery, mixed versions | sdk | P0 | IN PROGRESS | M2-10 | Replay twice yields identical DB | | M2-15 | Lag alerting and health metric | sdk | P1 | TODO | M2-12 | Alert fires in a simulated lag test | | M2-16 | Implement tier-3 verification and backfill per `M0-09` decision | sdk | P1 | TODO | M0-09, M2-06 | Old receipts verify; backfill fills a deliberate gap | -| M2-17 | SDK docs and API reference; publish testnet package versions | sdk | P0 | TODO | M2-07 | Published; docs match exports | -| M2-18 | Indexer container, testnet deployment, managed Postgres, daily backups | sdk | P0 | TODO | M2-14 | Running on testnet; restore tested once | -| M2-19 | Indexer and list API: store and filter payees by `country` and `local_currency` (display and filter only) | sdk | P0 | TODO | M2-13, M1-29 | `/payees?country=` works; no country logic elsewhere | +| M2-17 | SDK docs and API reference; publish testnet package versions | sdk | P0 | DONE | M2-07 | Published; docs match exports | +| M2-18 | Indexer container, testnet deployment, managed Postgres, daily backups | sdk | P0 | IN PROGRESS | M2-14 | Running on testnet; restore tested once | +| M2-19 | Indexer and list API: store and filter payees by `country` and `local_currency` (display and filter only) | sdk | P0 | DONE | M2-13, M1-29 | `/payees?country=` works; no country logic elsewhere | --- @@ -483,14 +484,16 @@ Resolve each with an ADR and link it here. Move resolved rows to the bottom with | ID | Task | Repo | Pri | Status | Depends on | Done when | |---|---|---|---|---|---|---| -| W-01 | Prepare Wave applications per repo (description, README, issues), within program limits | org | P1 | TODO | M0-10 | Applications submitted for the four active repos | -| W-02 | Seed issues: tests and docs in contracts (security-aware), registry tooling, app UI, SDK, indexer fixtures | all | P1 | TODO | M1-01 | Backlog exists; security-sensitive issues excluded from open contribution | +| W-01 | Prepare Wave applications per repo (description, README, issues), within program limits | org | P1 | IN PROGRESS | M0-10 | Applications submitted for the four active repos | +| W-02 | Seed issues: tests and docs in contracts (security-aware), registry tooling, app UI, SDK, indexer fixtures | all | P1 | DONE | M1-01 | Backlog exists; security-sensitive issues excluded from open contribution | | W-03 | Org and repo `CONTRIBUTING.md` including the roadmap rule | org | P0 | DONE | F-09 | Rule stated prominently | | W-04 | Contributor quick-start tested on a clean machine for each repo | all | P1 | TODO | M3-01 | New contributor runs tests in under 15 minutes | | W-05 | Issue sizing guide aligned with current program guidelines | org | P1 | TODO | M0-10 | Guide published | | W-06 | PR review SLAs and triage routine | org | P1 | TODO | F-12 | Documented; rota exists | | W-07 | Maintainer rota for `security-sensitive` PRs | org | P1 | TODO | F-12 | Named reviewers per week | | W-08 | Track application limits and KYC requirements per cycle | org | P2 | TODO | W-01 | Calendar and owner set | +| W-09 | SCF / open-source readiness audit against the official SCF Build Award handbook: license, contributor/community guidelines, roadmap-deliverable clarity (tranche-mapped), technical-integration brief | org | P1 | DONE | — | `docs/scf-readiness.md` published; `LICENSE` copyright line and `ISSUE_TEMPLATE/config.yml` gaps fixed and verified via the GitHub community-profile API | +| W-10 | Hosted documentation site covering all 4 repos and how they fit together, and the org's hub for filing/routing documentation issues | org | P1 | DONE | — | `Kinlock-Org/Kinlock-Org.github.io` published via GitHub Pages at `kinlock-org.github.io`; landing page plus one section per repo; links out to the canonical docs rather than duplicating them; linked from the org profile and every repo's README; documentation issue template, `area:*` labels, and `CONTRIBUTING.md` route doc gaps from any repo to this one | --- @@ -525,6 +528,7 @@ Newest first. One entry per PR. Required for every contribution (see §2). | Date | PR / ref | Repo | Rows touched | Summary | |---|---|---|---|---| +| 2026-10-08 | `chore/roadmap-reconcile` | org | canonical: 43 statuses corrected, rows M1-37 / M3-25 / M3-26 added; each repo copy: 36-52 statuses corrected, rows W-09 / W-10 added | First run of `scripts/roadmap-merge` (F-15) since the copies diverged at c488967 (2026-10-06). Three-way merge against that revision as ancestor: rows owned by a repo taken from that repo's copy, `org` / `all` rows from whichever copy changed them relative to the ancestor. One conflict adjudicated by hand: **F-11** - the canonical copy's reword and `DONE` (bea228e, ADR-0026) supersedes every repo copy's stale `IN PROGRESS`. **DEC-03** differed only in its ADR link prefix (`adr/` under `docs/`, `docs/adr/` at a repo root); `roadmap-merge` now normalizes that on read, so a path difference is never reported as a conflict. Root cause: each copy only ever advanced its own repo's rows, so every copy was stale for every other repo's rows too - 92 divergent statuses across the seven copies. Also corrects PR #25's changelog row, which was dated 2026-10-09 although the merge ran 2026-10-08 UTC. Progress table regenerated with `scripts/roadmap-progress`: **74 of 204 rows DONE, 41% readiness** | | 2026-10-08 | `feat/m3-24-country-agnostic-guard` | app | DONE: M3-24 | `M3-24` is a cross-cutting row ("all"); this PR plus a matching one in `kinlock-sdk` (PR #32 there) together complete it, so both mark it `DONE`. Added `lib/country-agnostic.test.ts`: fails if `nigeria`, `naira`, `ngn`, or `lagos` (case-insensitive, whole-word) appears anywhere under `app/`, `components/`, `lib/`, or `messages/`, excluding `*.test.ts`/`*.test.tsx`. Grounded in `AGENTS.md`'s own quick-reference wording ("Don't assume Nigeria or naira in code, tests, fixtures, or copy"), not a general country/currency-word ban, since this app's fixtures and UI deliberately exercise several real markets side by side (`messages/en.json` is included, since "copy" is explicitly in scope per that same rule). `docs/PRD.md`/`docs/ARCHITECTURE.md` are out of scope, since they legitimately narrate the pre-v0.3 "abroad to Nigeria" history. Runs via the existing `pnpm test` step already in CI, mirroring `lib/i18n/inline-strings.test.ts`'s existing pattern for a different check: no CI workflow changes needed. Verified the guard can actually fail: temporarily added a real violation to `lib/constants.ts`, confirmed it was caught with the exact term and file named, reverted (`git diff` empty), confirmed a clean pass. `pnpm lint`, `pnpm typecheck`, `pnpm test` (166/166), `pnpm build` all green | | 2026-10-08 | `feat/m3-14-fragment-leak-test` | app | DONE: M3-14 | The security headers, strict CSP, and no-third-party-scripts work was already built (`proxy.ts`, `lib/security/csp.ts`); the row's actual "Done when" (an automated test confirming the claim-link fragment never appears in any network request) didn't exist, and `lib/security/csp.test.ts` only unit-tests the CSP string builder, not real runtime behavior. Added `e2e/claim-fragment-privacy.spec.ts`: loads `/claim/11` (a real, already-existing testnet lock) with a real-shaped fragment, captures every outbound request for the page's lifetime (URL, body, headers), and fails if the reference or salt appears anywhere. Configured `playwright.config.ts` with a `webServer` (`pnpm build && pnpm start`, since `/claim/*`'s CSP differs between dev and production) and a `baseURL`, neither of which existed before. Verified the test can actually fail, not just trivially pass: temporarily injected a real leak into `useClaim.ts` (a stray `fetch` echoing the reference and salt), confirmed the test caught it with a clear diagnostic, then reverted (`git diff` confirms byte-identical to before) and confirmed a clean pass on the real code. Also caught and fixed two test-design bugs along the way: an invalid (non-`generateSalt()`-shaped) test salt silently made `parseClaimLink` throw before any of the code under test ran, and `waitForLoadState("networkidle")` never resolves on this page (it polls), so switched to a fixed wait. Verified: `pnpm lint`, `pnpm typecheck`, `pnpm test` (108/108), `pnpm build`, and the E2E test itself, run manually multiple times. **Not done here**: wiring this into CI. `.github/workflows/e2e.yml` is marked `DRAFT (ask-first: CI)` and currently just echoes a placeholder; actually running `pnpm e2e` there needs a human to approve editing the workflow file, per `AGENTS.md`'s CI/CD ask-first rule. No new secrets needed (all required env vars are the existing public `NEXT_PUBLIC_*` testnet config) | | 2026-10-08 | `docs/m3-06-testnet-verification` | app | M3-06 (status unchanged, `IN PROGRESS`) | Attempted the owner's ask to verify `/send` by driving the live app with a real testnet wallet. Got substantially further than "can't automate a browser extension": `@creit.tech/stellar-wallets-kit`'s Albedo option is web-based (no extension) and exposes "provide secret key directly," reachable via Playwright against the real `kinlock-app.vercel.app/send` all the way to the secret-entry field. Writing the secret into any file or process for that automation was blocked outright by the harness's credential-materialization check, including after the owner pasted it directly into the conversation; did not attempt to work around that. Fell back to proving the layer underneath instead: called the deployed contract's `create_lock` directly via `stellar contract invoke` (using a CLI-keystore identity by name, so no secret was ever materialized by this agent), from a freshly generated, friendbot-funded sender account with a real Circle testnet-USDC trustline and balance (owner completed the faucet's human-verification step). Simulated first, then submitted for real: lock id `11` created on the live testnet contract (tx `0b65ec01b50052bac645242c9d375151c4a2b7517856340504d5b7aa46d2042a`, verifiable on stellar.expert), 2 USDC transferred to the contract, correct payee/payout snapshot. Confirmed the indexer picked it up correctly (`/locks/11` matches the submitted transaction exactly) and that the live app's own `/locks/11` and `/claim/11` pages render it (`200`, real chain data). This proves the contract and SDK path End to end on testnet, the thing `/send`'s own code depends on, but does **not** prove `/send`'s own `useSendForm.ts` → wallet-kit → `createLock()` code path specifically, since the actual signing step was bypassed via direct CLI rather than driven through the app. Narrowing what's left for `M3-06`: a human completing the Albedo "provide secret key" step themselves in their own browser against the live site, or a CI-sanctioned signing approach for `M3-19` (still an open, deferred decision) | @@ -542,6 +546,29 @@ Newest first. One entry per PR. Required for every contribution (see §2). | 2026-10-08 | `docs/live-app-link` | app | no row changes | Linked the live testnet app from this repo's own README; also set org-wide (org website field, `.github` profile README) and on every repo's GitHub "Website" field | | 2026-10-08 | `feat/m3-04-landing-page` | app | IN PROGRESS: M3-22 | Deployed to Vercel via CLI: production URL `https://kinlock-app.vercel.app`, all pages verified `200` (`/`, `/send`, `/request`, `/verify`, `/payee`, `/attester`). Set the 5 public, non-secret `NEXT_PUBLIC_*` env vars from the real testnet deployment records (contract ID, USDC contract/issuer, RPC URL); left `NEXT_PUBLIC_INDEXER_URL` unset since no indexer is deployed yet (`M2-18`, separate task) - indexer-dependent pages (`/send`, `/request`, `/payee`) degrade gracefully to their existing "can't load the list right now" state rather than breaking. GitHub auto-deploy-on-push could not be connected: the Vercel account's GitHub identity lacks admin/write on `Kinlock-Org/kinlock-app`, so future deploys need a manual `vercel --prod` (or fixing that GitHub App authorization) until resolved. Left `IN PROGRESS`, not `DONE`: the row formally depends on `M3-19` (E2E happy-path against testnet), which is still `TODO` | | 2026-10-08 | `feat/m3-04-landing-page` | app | DONE: M3-04 | Built the real landing page at `(marketing)/page.tsx` (hero, how-it-works, sender/payee split, principles, footer), replacing the `PageStub`. Added a site-wide testnet-safety banner (`common.testnetBanner`) to `layout.tsx` so it's visible on every page, not just the homepage. Added `Outfit` via `next/font/google` and a light/dark color-token system in `globals.css` (no new npm dependency). Content reviewed against hard rule 7 (honest receipt wording), no hard-coded country/currency, no fabricated traction/testimonials (none exist yet, so none are claimed), zero em-dashes. Verified: `pnpm lint`, `pnpm typecheck`, `pnpm test` (79/79 passed), `pnpm build` all green. Confirms the app needs a Node runtime (dynamic routes + proxy middleware), ruling out GitHub Pages for `M3-22`. Also installed `anthropics/skills` frontend-design and `Leonxlnx/taste-skill` design-taste-frontend as local dev tooling (gitignored, not committed) | +| 2026-10-08 | `docs/readme-refresh` | org | no row changes | Rewrote the org profile README: what Kinlock proves and what it does not, every repo including the docs hub and the conditional `kinlock-ramp`, the principles, the trust assumptions, and the every-PR `ROADMAP.md` rule. Folds in the pending verified-payee wording and the docs-hub links | +| 2026-10-08 | `docs/docs-hub-link` (org) + `Kinlock-Org.github.io#1` | org | DONE: W-10 (expanded scope, no status change) | Repositioned the docs site repo as the org's documentation-issue hub, not just a static site: a documentation issue template, `area:contract`/`area:sdk`/`area:app`/`area:registry`/`area:site` labels for routing, a new `CONTRIBUTING.md` explaining where a fix actually lands (that repo, if it needs code; the canonical `.github` docs, if it's architecture/PRD/ADRs; this repo, if it's the site itself), and a "File a documentation issue" section on the landing page. Linked from the org profile | +| 2026-10-08 | `docs/live-app-link` (org) + direct push to new repo `Kinlock-Org.github.io` | org | DONE: W-10 (new row) | Published a hosted documentation site at `kinlock-org.github.io` (plain static HTML/CSS, no framework, no build step): a landing page explaining how the 4 repos fit together, plus one section per repo summarizing real facts (entry points, invariants, public API, testnet contract ID, test counts) with links out to the canonical docs for full depth, not a duplicate copy. Linked from the org profile README and every repo's own README. Pushed directly to `main` (new, empty repo, nothing to review against yet) | +| 2026-10-08 | `docs/m0-04-cost-model-template` | org | DONE: F-13 (found undone from an earlier pass). IN PROGRESS: M0-04 | Rebuilt on current `main` after `chore/f12-f16-governance` (#18) merged, to avoid a `ROADMAP.md` conflict. Added `docs/research/m0-04-cost-model-template.md`: the hop-by-hop cost structure `M0-04` asks for, seeded with cited public benchmarks (World Bank Remittance Prices Worldwide global average 6.49%; USDC on/off-ramp fee ranges; Stellar's ~$0.0001 on-chain fee) — explicitly illustrative, not Kinlock-specific; real numbers still need `M0-01` and `M0-05`, neither run yet. `M0-13` stays `TODO`, still blocked on this. Also closed `F-13` (label set): labels were actually created and verified across all 4 active repos in an earlier session pass, but the row was never flipped from `TODO` | +| 2026-10-08 | `feat/m3-24-country-agnostic-guard` | sdk | DONE: M3-24 | `M3-24` is a cross-cutting row ("all"); this PR plus a matching one in `kinlock-app` together complete it, so both mark it `DONE`. Added `packages/sdk/src/__tests__/country-agnostic.test.ts` and `services/indexer/test/country-agnostic.test.ts`: fails if `nigeria`, `naira`, `ngn`, or `lagos` (case-insensitive, whole-word) appears anywhere in source, excluding `*.test.ts` files. Grounded in `AGENTS.md`'s own quick-reference wording ("Don't assume Nigeria or naira"), not a general country/currency-word ban, since this project's fixtures and app deliberately exercise several real markets side by side; docs (`docs/PRD.md`, `docs/ARCHITECTURE.md`) are out of scope since they legitimately narrate the pre-v0.3 Nigeria-specific history. Runs via the existing `pnpm test` step already in both `packages/sdk` and `services/indexer`'s CI, so no workflow file changes were needed (same pattern `kinlock-app`'s `lib/i18n/inline-strings.test.ts` already uses for a different check). Verified the guard can actually fail, not just trivially pass: temporarily added a real violation to a file in each package, confirmed both caught it with the exact file named, reverted (`git diff` on both files is empty), confirmed a clean pass. `pnpm lint`, `pnpm typecheck`, `pnpm test` (165/165), `pnpm build` all green | +| 2026-10-08 | `docs/readme-refresh` | sdk | no row changes | README was stale: it said the indexer is still being scaffolded, but it is built and running on testnet. Now documents the 16 public exports, the `bigint` and claim-link-fragment invariants, the list API routes, and the live indexer | +| 2026-10-08 | `docs/m2-17-api-reference` | sdk | DONE: M2-17 | Added `packages/sdk/API.md`: every public export (client, preflight, receipts, links, hash, format, errors, types) documented with real signatures, params, return types, and a runnable usage example, read directly from the current `src/*.ts` source, not from memory. Linked from README. Verified: `pnpm lint`, `pnpm typecheck`, `pnpm test` (123/123 passed) all green. Closes issue #25 (seeded under `W-02`) | +| 2026-10-08 | `docs/verified-payee-wording` | sdk | no row changes | Synced `AGENTS.md`/`docs/PRD.md`/`docs/ARCHITECTURE_ESSENTIALS.md` from `Kinlock-Org/.github` (`scripts/sync-docs.sh`): "a verified school or landlord" in the mission-statement-style sentences replaced with "a verified payee." Canonical source edited in `.github` PR #23 | +| 2026-10-08 | `docs/link-doc-hub` | sdk | no row changes (org row W-10 tracked in `.github`) | Linked `Kinlock-Org.github.io` (the org's documentation-issue hub) from README, with `area:sdk` | +| 2026-10-08 | `docs/docs-site-link` | sdk | no row changes (org row W-10 tracked in `.github`) | Linked the new hosted docs site (`kinlock-org.github.io`) from README | +| 2026-10-08 | `docs/live-app-link` | sdk | no row changes | Linked the live testnet app (`kinlock-app.vercel.app`, `M3-22`) from README; also set as the repo's GitHub "Website" field | +| 2026-10-08 | `docs/fix-entry-point-count` | contracts | no row changes | Corrected the README status banner: it claimed "All 20 entry points," but the single `#[contractimpl]` in `contracts/kinlock/src/lib.rs` exposes **18** (`__constructor` plus 17 callable). Counted directly from `lib.rs:29-136`; `admin.rs`/`registry.rs`/`vault.rs` hold internal implementations, not extra entry points. No other file in the workspace repeats the wrong number | +| 2026-10-08 | `docs/verified-payee-wording` | contracts | no row changes | Synced `AGENTS.md`/`docs/PRD.md`/`docs/ARCHITECTURE_ESSENTIALS.md` from `Kinlock-Org/.github` (`scripts/sync-docs.sh`): "a verified school or landlord" in the mission-statement-style sentences replaced with "a verified payee." Canonical source edited in `.github` PR #23 | +| 2026-10-08 | `docs/link-doc-hub` | contracts | no row changes (org row W-10 tracked in `.github`) | Linked `Kinlock-Org.github.io` (the org's documentation-issue hub) from README, with `area:contract` | +| 2026-10-08 | `docs/m1-21-threat-model` | contracts | DONE: M1-21 | Expanded `SECURITY.md`'s threat model (was "draft pending"): a table linking each of the 10 property-tested invariants to exactly where `properties.rs::check_invariants` checks it and a representative unit test, plus a threats-to-controls table enriched with invariant numbers and the tests that verify each one. Cites real mutation-testing and independent-review evidence from the Changelog. Verified by actually running the suite: `cargo test --workspace` (107 unit tests, 1 property test, all green), `cargo fmt --all -- --check` and `cargo clippy --all-targets -- -D warnings` clean. Closes issue #17 (seeded under `W-02`) | +| 2026-10-08 | `docs/docs-site-link-fix` | contracts | no row changes (org row W-10 tracked in `.github`) | Re-added the hosted-docs-site link to README; a prior PR (#19) merged before its second commit adding this same link finished pushing, so it never landed the first time | +| 2026-10-08 | `docs/live-app-link` | contracts | no row changes | Linked the live testnet app (`kinlock-app.vercel.app`, `M3-22`) from README; also set as the repo's GitHub "Website" field | +| 2026-10-08 | `docs/readme-refresh` | registry | no row changes | README corrected: fixtures span three countries (KE, NG, PH), not two, and the real `payees/` and `attesters/` trees are still empty pending the `M0-17` supported-countries policy. Documents what CI enforces off-chain and the attester readiness script | +| 2026-10-08 | `docs/link-doc-hub` | registry | no row changes (org row W-10 tracked in `.github`) | Linked `Kinlock-Org.github.io` (the org's documentation-issue hub) from README, with `area:registry` | +| 2026-10-08 | `docs/verified-payee-wording` | registry | no row changes | Synced `AGENTS.md`/`docs/PRD.md`/`docs/ARCHITECTURE_ESSENTIALS.md` from `Kinlock-Org/.github` (`scripts/sync-docs.sh`): "a verified school or landlord" in the mission-statement-style sentences replaced with "a verified payee." Canonical source edited in `.github` PR #23. Left `fixtures/README.md`'s "not real schools or landlords" unchanged (factual fixture disclaimer, not pitch copy) | +| 2026-10-08 | `docs/m1-26-attester-script` | registry | IN PROGRESS: M1-26 | Added `scripts/check-attester-readiness.ts` (`pnpm check-attester-readiness `): read-only checks for account existence, native XLM float, and an authorized USDC trustline with room, via direct ledger-entry reads (no new dependency). Verified against real testnet data, not just type-checked: ran it against the real testnet attester address and confirmed correct output (XLM float ✓, trustline ✗ as expected, since that address has none). Finalized `ATTESTER_CHECKLIST.md` to reference the script. Left `IN PROGRESS`, not `DONE`: the row's "runs end to end on testnet" criterion needs a real attester to complete it (`M0-06`), which hasn't happened. Progress toward issue #7 (seeded under `W-02`), not a full close | +| 2026-10-08 | `docs/docs-site-link` | registry | no row changes (org row W-10 tracked in `.github`) | Linked the new hosted docs site (`kinlock-org.github.io`) from README | +| 2026-10-08 | `docs/live-app-link` | registry | no row changes | Linked the live testnet app (`kinlock-app.vercel.app`, `M3-22`) from README; also set as the repo's GitHub "Website" field | | 2026-10-07 | `docs/scf-readiness-fixes` | app | no row changes (org rows W-09/F-12 tracked in `.github`) | Part of an org-wide SCF open-source readiness audit (see `.github` `docs/scf-readiness.md`): filled the unfilled `Copyright [yyyy] [name of copyright owner]` placeholder in `LICENSE` and added `ISSUE_TEMPLATE/config.yml` (GitHub's community-profile check was reporting `issue_template: false` despite templates existing) | | 2026-10-07 | `docs/readme-status-banner` | app | no row changes | README said "scaffold... features are not built," which is stale (send, claim, decline, and lock-detail flows work end to end on testnet). Corrected the status banner to match current progress; supports org-level `W-01` Wave-readiness | | 2026-10-07 | kinlock-app feat/app-send-flow | app | M3-06 IN PROGRESS, M3-05 DONE | `/send`: verified payees (indexer list, server-side), prefill from a request link (M3-05 now pre-fills the form), schedule and take-back date checked like `create_lock`, USD with the USD-only rate note (DEC-10 open), wallet, preflight review (blocking failures stop; warnings need acknowledgement), lock via the wallet, claim link built and saved in this browser. Indexer list API served same-origin via rewrites (no CORS). Creating a lock through a real wallet still to verify | @@ -553,8 +580,55 @@ Newest first. One entry per PR. Required for every contribution (see §2). | 2026-10-07 | kinlock-app feat/app-request-page | app | M3-05 IN PROGRESS | `/request`: payee picks a verified payee (list from the indexer, server-side), reference and up to 12 dated payments; the SDK builds the link in the browser. Says the link carries no authority and that the reference is visible to link holders. Done once `/send` pre-fills from it (M3-06) | | 2026-10-07 | kinlock-app feat/app-sdk-config | app | M3-03 DONE | `lib/sdk.ts` is the single SDK entry point over `@kinlock/sdk` 0.2.0 (GitHub Release): config bound once, wallet adapter bridged to the SDK signer. `lib/config.ts` validates the public env (adds the USDC token contract ID; mainnet refused). Started while M2-02 is IN PROGRESS (local-network run pending), as with M2-06. Docs synced (ADR-0026..0029) | | 2026-10-07 | kinlock-app docs/sync-adr-0026 | app | DEC-03 amended (no row changes) | Sync docs from .github: ADR-0026 (packages as GitHub Release tarballs) and ADR-0023 marked superseded | +| 2026-10-07 | `chore/f16-branch-protection` | org | DONE: F-16 | Applied branch protection to `main` on all 5 repos: required status checks (repo-specific CI jobs, confirmed via recent PR check names so none are a path-filtered context that would never report), 1 required approving review + CODEOWNERS review, no force-push, no deletion. `.github` has no CI so only PR-required + no-force-push/delete there. This is a workflow change: merges now need an actual approval, not just green CI | +| 2026-10-07 | `chore/f12-teams` | org | DONE: F-12 | Created `maintainers` (abrcrmb, YazarAyobami, maintain access on all 5 repos), `contract-reviewers` (abrcrmb, YazarAyobami, maintain access on kinlock-contracts/sdk/app), and `attesters` (empty, push access on kinlock-registry so its `payees/**` rule resolves). Verified: `GET /repos/{repo}/codeowners/errors` returns zero errors on all 4 active repos (previously all failed with "Unknown owner"). Unblocks `F-16` (branch protection), `W-06`, `W-07` | +| 2026-10-07 | `chore/w02-seed-issues` | org | DONE: W-02 | Seeded 5 Wave-scoped issues from existing roadmap rows across all 4 active repos: `kinlock-app#15` (M3-17 accessibility), `kinlock-app#16` (M3-20 copy review), `kinlock-sdk#25` (M2-17 docs), `kinlock-registry#7` (M1-26 attester checklist), `kinlock-contracts#17` (M1-21 threat-model docs, docs-only). All drawn from `project_structure.md` §8's "safe for broad contribution" list; none touch fund logic, auth, or claim-link-fragment code. Unblocked by `kinlock-contracts` closing `M1-01` this same pass | +| 2026-10-07 | `docs/scf-readiness` | org | DONE: W-09 (new row). IN PROGRESS: M0-14 | Audited Kinlock against the official SCF Build Award handbook (license, contributor/community guidelines, roadmap-deliverable clarity, technical-integration brief, differentiation). Fixed the unfilled `Copyright [yyyy] [name of copyright owner]` placeholder in every repo's `LICENSE` (→ "Kinlock Contributors," pending `DEC-13`) and added `ISSUE_TEMPLATE/config.yml` (GitHub's community-profile check was reporting `issue_template: false` despite the templates existing). Found `CODEOWNERS` is non-functional — it references `F-12` teams that don't exist yet. Could not verify "BarakahPay" as a real product via web search; found real comparables (RemitaPay, Circle Arc "Remit") instead. Full findings and "needs a human" list in `docs/scf-readiness.md` | +| 2026-10-07 | `docs/m0-10-wave-rules` | org | DONE: M0-10. IN PROGRESS: W-01 | Added `docs/research/m0-10-wave-rules.md`: Drips Stellar Wave mechanics (issue sizing tiers, per-user/per-org repo-application limits that reset each cycle, KYC required to submit an application and to withdraw rewards), sourced from official docs. Confirms the existing plan to apply only the four active repos; flags KYC as a blocking prerequisite for a human to complete before `W-01` can reach `DONE`. One `wave` label created on `kinlock-contracts` toward `F-13`; the full label rollout across all four repos is prepared as a script for the maintainer to run (bulk label writes across repos were blocked for the agent) | +| 2026-10-07 | `docs/m0-interview-materials` | org | IN PROGRESS: M0-01, M0-02, M0-03 | Added `docs/research/` with a sender interview script + note template (M0-01), payee interview script + note template (M0-02), and an attester conversation guide (M0-03), each mapped to `PRD.md` §8.2 pivot triggers and §10 assumptions, with log tables for findings. Scripts/templates only — no real interviews conducted yet, so rows stay `IN PROGRESS` pending actual notes and the themes summary | +| 2026-10-07 | .github docs/adr-sdk-getpayee | org | no row changes | ADR-0030: SDK gains `getPayee` (chain read) so money pages apply the full refund rule; AGENTS.md §8.2 lists it | +| 2026-10-07 | .github docs/adr-receipts | org | no row changes | ADR-0029: receipt verification tiers and results; indexer event lookup as a tier-2 aid | +| 2026-10-07 | .github docs/adr-sdk-preflight | org | no row changes | ADR-0028: SDK preflight results (pass/fail/unknown with block/warn severity), optional `indexerUrl` for the two indexer-backed warnings | +| 2026-10-07 | .github docs/adr-sdk-client | org | no row changes | ADR-0027: SDK contract functions take a config first and a wallet signer last; new types `KinlockConfig`, `Signer`; error codes `INVALID_INPUT`, `CONTRACT_ERROR`, `TX_FAILED` | +| 2026-10-07 | .github docs/reword-f11 | org | F-11 DONE (reworded, owner-approved) | F-11 reworded from npm to "package names and distribution"; done: `@kinlock/contract` 0.1.0 and `@kinlock/sdk` 0.1.0 released as GitHub Release tarballs and installed from their URLs. ADR-0026 corrected: pnpm lockfiles do not record an integrity hash for URL tarballs | +| 2026-10-07 | .github docs/adr-github-release-packages | org | DEC-03 amended | ADR-0026: distribute `@kinlock/contract` and `@kinlock/sdk` as GitHub Release tarballs (no npm account or token); supersedes ADR-0023 | +| 2026-10-07 | `docs/scf-readiness-fixes` | sdk | no row changes (org rows W-09/F-12 tracked in `.github`) | Part of an org-wide SCF open-source readiness audit (see `.github` `docs/scf-readiness.md`): filled the unfilled `Copyright [yyyy] [name of copyright owner]` placeholder in `LICENSE` and added `ISSUE_TEMPLATE/config.yml` (GitHub's community-profile check was reporting `issue_template: false` despite templates existing) | +| 2026-10-07 | `docs/readme-status-banner` | sdk | no row changes | README said "scaffold... features are not built," which is stale (client, preflight, and receipts are implemented and released as v0.3.0). Corrected the status banner to match current progress; supports org-level `W-01` Wave-readiness | +| 2026-10-07 | kinlock-sdk feat/sdk-getpayee | sdk | no row changes | `getPayee` chain read (ADR-0030) for the sender lock page's refund rule; `@kinlock/sdk` 0.3.0 (release via tag `sdk-v0.3.0` after merge). Verified on testnet | +| 2026-10-07 | kinlock-sdk test/sdk-localnet | sdk | M2-02 DONE | SDK client verified on the local quickstart network (fresh contract, local USDC, one payee: preflight, create, read, release, refused early refund, decline) and again on testnet; full refund verified on testnet (lock 4). Smoke script renamed `scripts/smoke.mjs` and parameterized for local or testnet | +| 2026-10-07 | kinlock-sdk chore/sdk-0.2.0 | sdk | M2-17 IN PROGRESS (unchanged) | `@kinlock/sdk` 0.2.0: first release with the contract client, preflight and receipt verification (0.1.0 had them as stubs); signatures per ADR-0027..0029. Released via tag `sdk-v0.2.0` after merge | +| 2026-10-07 | kinlock-sdk feat/sdk-receipts | sdk | M2-06 DONE | SDK `verifyReceipt` (ADR-0029): tier 1 from RPC events (exact event, Kinlock contract, successful call, known schema version), tier 2 confirmed with `get_lock` after the indexer event lookup; reasons verified / not_found / mismatch / unverifiable. Real testnet release, decline and refund receipts verified; tampered references rejected | +| 2026-10-07 | kinlock-sdk feat/indexer-event-lookup | sdk | M2-06 IN PROGRESS | List API `GET /events/:txHash/:eventIndex`: which lock and tranche a receipt refers to, as a lookup aid for tier-2 receipt verification (proof stays on chain). Started while M2-02 is IN PROGRESS (local-network run pending), with owner approval | +| 2026-10-07 | kinlock-sdk feat/sdk-preflight | sdk | M2-05 DONE | SDK `preflight` (ADR-0028): sender balance, payee Active and payout trustline from chain (block); recent payout change and duplicate reference from the indexer (warn); `unknown` when a check can't complete. Unit test per check; testnet run with the live indexer passed all five | +| 2026-10-07 | kinlock-sdk feat/indexer-preflight-filters | sdk | M2-05 IN PROGRESS | List API filters for preflight: `GET /locks?payee_id=&ref_hash=` (duplicate reference, uses the existing (payee_id, ref_hash) index) and `GET /payees?payee_id=` (recent payout change) | +| 2026-10-07 | kinlock-sdk feat/sdk-client | sdk | M2-02 IN PROGRESS | SDK client over `@kinlock/contract` 0.1.0 (GitHub Release): `createLock`, `release`, `refund`, `decline` (build, simulate, wallet signs, submit) and chain-only `getLock`, with config and signer parameters (ADR-0027). Verified on testnet (create, read, release, refused early refund, decline); local-network run not done (no Docker on the dev machine) | +| 2026-10-07 | kinlock-sdk chore/sdk-github-release | sdk | M2-17 IN PROGRESS (unchanged), DEC-03 amended | `publish` workflow attaches the packed `@kinlock/sdk` tarball to a GitHub Release on `sdk-vX.Y.Z` (ADR-0026) instead of publishing to npm; no publish secret; ADR-0026 synced | +| 2026-10-07 | kinlock-sdk docs/indexer-testnet-deployed | sdk | M2-18 IN PROGRESS (unchanged) | Indexer live on Railway testnet (https://indexer-production-705a.up.railway.app): caught up, registry join working, refund of lock 2 indexed within seconds. Postgres PITR enabled and a point-in-time restore into a new service succeeded; still open: daily schedule refused on the current plan, and the restored data not yet compared against live | +| 2026-10-07 | kinlock-sdk test/indexer-real-refund-fixture | sdk | no row changes | Indexer fixtures: add the real testnet `refunded` event for lock 2 (tx 7316fe69…) and replace the synthetic refund in the tests; replay now ends with lock 2 Refunded/Expired | +| 2026-10-07 | `docs/m1-01-done` | contracts | DONE: M1-01 | Verified CI green on `main` (fmt/clippy/test/build) and `scripts/localnet.sh` + `scripts/localnet-setup.sh` both present and merged (`chore/localnet-setup`, PR #14). `M1-01` formally depends on gate `G1` (not yet passed) — closing this row now, ahead of G1, follows the same precedent as the rest of Phase 2's work, done ahead of G1 at the owner's request. This unblocks `W-02` (seed issues), which depended on `M1-01` | +| 2026-10-07 | `docs/scf-readiness-fixes` | contracts | no row changes (org rows W-09/F-12 tracked in `.github`) | Part of an org-wide SCF open-source readiness audit (see `.github` `docs/scf-readiness.md`): filled the unfilled `Copyright [yyyy] [name of copyright owner]` placeholder in `LICENSE` and added `ISSUE_TEMPLATE/config.yml` (GitHub's community-profile check was reporting `issue_template: false` despite templates existing) | +| 2026-10-07 | `docs/readme-status-banner` | contracts | no row changes | README said "scaffold... features are not built," which is stale (vault/registry entry points are implemented and tested). Corrected the status banner to match current progress; supports org-level `W-01` Wave-readiness | +| 2026-10-07 | kinlock-contracts chore/localnet-setup | contracts | M1-37 added, DONE | `scripts/localnet-setup.sh`: fresh local Kinlock in one command (local only; refuses other networks); verified on a fresh quickstart network, then the SDK smoke test passed with its env block (owner-approved new row). Docs synced (ADR-0028, ADR-0029) | +| 2026-10-07 | kinlock-contracts docs/m1-18-done | contracts | M1-18 DONE | `@kinlock/contract` 0.1.0 released on tag `bindings-v0.1.0` (GitHub Release, ADR-0026); installs from its URL and the SDK consumes it (kinlock-sdk#15, testnet run passed). Docs synced (ADR-0026 correction, ADR-0027) | +| 2026-10-07 | kinlock-contracts chore/bindings-github-release | contracts | M1-18 IN PROGRESS (unchanged), DEC-03 amended | `bindings` workflow attaches the packed `@kinlock/contract` tarball to a GitHub Release on `bindings-vX.Y.Z` (ADR-0026) instead of publishing to npm; no publish secret; docs synced (ADR-0024..0026, AGENTS.md) | +| 2026-10-07 | `docs/scf-readiness-fixes` | registry | no row changes (org rows W-09/F-12 tracked in `.github`) | Part of an org-wide SCF open-source readiness audit (see `.github` `docs/scf-readiness.md`): filled the unfilled `Copyright [yyyy] [name of copyright owner]` placeholder in `LICENSE` and added `ISSUE_TEMPLATE/config.yml` (GitHub's community-profile check was reporting `issue_template: false` despite templates existing) | +| 2026-10-07 | `docs/readme-status-banner` | registry | no row changes | README said "scaffold... features are not built," which is stale (schema validation, hashing, and on-chain match checks are implemented with testnet fixtures). Corrected the status banner to match current progress; supports org-level `W-01` Wave-readiness | +| 2026-10-07 | kinlock-registry docs/sync-adr-0026 | registry | DEC-03 amended (no row changes) | Sync docs from .github: ADR-0026 (packages as GitHub Release tarballs) and ADR-0023 marked superseded | | 2026-10-06 | `feat/app-foundations` | app | DONE: M3-23. IN PROGRESS: M3-02, M3-14, M3-15 | Wallet adapter on Stellar Wallets Kit (browser-only); AssetLabel (code + issuer, full issuer for screen readers), AmountDisplay and DateTimeDisplay (UTC + local) on Intl with exact decimal strings; inline-string check and formatting tests across en/de/hi/ar/ja and USD/JPY/KWD. Claim pages get a per-request nonce CSP via proxy.ts (verified on a production build: all 8 Next.js scripts carry the nonce; the old static `script-src 'self'` would have blocked them). Fixed a date formatter that would have thrown | +| 2026-10-06 | `docs/sdk-public-api` | org | no row changes | ADR-0025: SDK public API gains amount conversion, reference hashing, and request-link helpers (owner-approved); AGENTS.md §8.2 updated | +| 2026-10-06 | `docs/adr-ref-hash` | org | no row changes | ADR-0024: exact reference-hash and claim-link format (16-byte base64url salt; SHA-256 of NFC-trimmed UTF-8 reference followed by salt bytes; fragment-only claim links), as implemented in kinlock-sdk | | 2026-10-06 | `chore/license-and-publishing` | org | DONE: F-10. IN PROGRESS: F-11. DEC-02, DEC-03 resolved | Apache-2.0 for every repo (ADR-0022, `LICENSE` + template); TypeScript packages publish to npm under `@kinlock` from CI on tag (ADR-0023). F-11 waits on an owner creating the npm org and the `NPM_TOKEN` secret. Canonical roadmap re-merged from all repos (picks up M2-01, M3-01). `sync-docs.sh --check` now also fails on ADRs a repo has that the canonical copy lacks (it missed that drift before) | +| 2026-10-06 | kinlock-sdk feat/indexer-deploy | sdk | M2-18 IN PROGRESS | Indexer container (Dockerfile, registry clone at start, migrations before start), `railway.json`, CI job that builds the image and applies migrations against Postgres, Railway runbook with backup and restore-test steps. Not yet deployed: needs the Railway project and variables | +| 2026-10-06 | kinlock-sdk feat/indexer-registry-join | sdk | M2-13 DONE, M2-19 DONE | Registry join: payee name, city, country, local currency and attester handle come from a registry checkout (`REGISTRY_DIR`), shown only when the file is hash-bound to the on-chain registration (payee_id = sha256(slug), meta_hash = sha256(canonical file)); attester handle only when its address matches on-chain; `/payees?country=` filters on joined data; migration 0001 adds `payees.attester_handle` | +| 2026-10-06 | kinlock-sdk feat/indexer-list-api | sdk | M2-12 DONE | List API: `/locks` (sender, payee, state filters; paging), `/locks/:id` with tranches, `/payees` (category, country, text filters; paging), `/health` with ledger lag (503 when lagging or tip unknown); every response labeled `source: "indexer"` with the ledger it reflects; typed request/response contract in `api/schemas.ts`. Started while M2-10 is IN PROGRESS (only its mixed-version test remains), with owner approval | +| 2026-10-06 | kinlock-sdk feat/indexer-ingest | sdk | M2-08 DONE, M2-09 DONE, M2-10 IN PROGRESS, M2-11 DONE, M2-14 IN PROGRESS | Indexer core: RPC client with failover and Zod checks, cursor-based ingest that commits events, effects and cursor in one transaction and stops on gaps or unknown events, handlers for all 7 events (schema_version 1), initial migration, PGlite tests replaying 11 recorded testnet events. Mixed-version fixtures wait for a second schema_version | +| 2026-10-06 | `feat/sdk-publish` | sdk | IN PROGRESS: M2-17 | `@kinlock/sdk` 0.1.0 made publishable (exports map, `dist/` only, public access) and a tag-triggered publish workflow (`sdk-vX.Y.Z`, checks + npm provenance). Verified by installing the packed tarball into a blank project and calling it. Not yet published: waits on `NPM_TOKEN` (F-11) | +| 2026-10-06 | `feat/sdk-public-api` | sdk | no row changes | Public API gains `toBaseUnits`, `fromBaseUnits`, `generateSalt`, `computeRefHash`, `buildRequestLink`, `parseRequestLink` (owner-approved, ADR-0025); the pinned export test now lists 15 functions. AGENTS.md and docs synced | +| 2026-10-06 | `feat/sdk-format-hash-links` | sdk | DONE: M2-03, M2-04, M2-07 | Exact amount conversion (never rounds); `ref_hash` = SHA-256(UTF-8(NFC-trimmed reference) ‖ 16 random salt bytes) (ADR-0024); claim links carry reference and salt only in the URL fragment; request-link helpers built but not exported (public API list, F-19). 49 tests incl. an independent hash check and a no-logging test; 4 mutation checks caught | +| 2026-10-06 | `fix/bindings-errors-sdk17` | contracts | no row changes (M1-18 stays IN PROGRESS) | Every contract error variant now has a doc comment (`Name: explanation`); stellar-sdk takes client error messages from these, so they were empty before. Bindings pinned to `@stellar/stellar-sdk` 17.2.1 (same as kinlock-sdk). Verified live on testnet: errors decode as e.g. "PayeeNotFound: no payee is registered with this ID." | +| 2026-10-06 | `feat/ts-bindings` | contracts | IN PROGRESS: M1-18 | Generated TypeScript bindings committed as `@kinlock/contract` 0.1.0; `gen-bindings.sh` sets package metadata; tag-triggered publish workflow (`bindings-vX.Y.Z`, npm provenance) and a CI check that committed bindings match a fresh generation. Not yet published: waits on the npm org and `NPM_TOKEN` (F-11) | +| 2026-10-06 | `feat/registry-validation` | registry | DONE: M1-24, M1-25, M1-27, M1-29 | Registry validation (Ajv schemas, canonical formatting, supported country, attester scope, folder match, unique slug, real ISO codes) with 16 failing-case tests; `hash` and `check-onchain` tools. Three fictional fixture payees (KE, NG, PH; School and Rent) with funded testnet payouts holding authorized USDC trustlines, registered on testnet by the attester; `check-onchain` confirms all three match and catches a mismatch. Real `supported-countries.json` unchanged (empty) | +| 2026-10-06 | `chore/license-and-publishing` | org | DONE: F-10. IN PROGRESS: F-11. DEC-02, DEC-03 resolved | Apache-2.0 for every repo (ADR-0022, `LICENSE` + template); TypeScript packages publish to npm under `@kinlock` from CI on tag (ADR-0023). F-11 waits on an owner creating the npm org and the `NPM_TOKEN` secret. Canonical roadmap re-merged from all repos (picks up M2-01, M3-01) | | 2026-10-06 | `chore/ts-tooling` | sdk | DONE: M2-01. DEC-22, DEC-23 resolved (ADR-0021) | Biome (lint + format), Vitest, and tsx added; CI now runs lint, typecheck, test, and build. Tests pin the SDK's public API to the approved list and the contract's enum order, and check the indexer refuses bad config | | 2026-10-06 | `chore/roadmap-sync` (lockfile) | sdk | no row changes (M2-01 stays IN PROGRESS: lint and test tooling pending DEC-22) | Commit `pnpm-lock.yaml` for the dependency versions approved by the owner on 2026-10-06, so CI's frozen install works; typecheck and build pass | | 2026-10-06 | `chore/ts-tooling` | app | DONE: M3-01. DEC-22, DEC-23 resolved (ADR-0021) | Biome (lint + format) and Vitest added; CI now runs lint, typecheck, test, and build. Tests keep the receipt wording exactly "Payment to verified payee", ban overclaiming wording, and check every message key resolves. M3-23 stays IN PROGRESS (inline-string lint and multi-locale formatting tests) |