From 3de20ed89d86ffdfe5d912734eb1dc4328895abb Mon Sep 17 00:00:00 2001 From: George Coles Date: Tue, 15 Sep 2026 11:59:30 -0400 Subject: [PATCH] Signup without a code queues a pending application; registry approve issues credentials --- AGENTS.md | 2 +- DEPLOY.md | 2 +- src/commands.rs | 191 +++++++++++++++++++++++++++++++++----------- src/main.rs | 8 ++ src/registry.rs | 36 ++++++++- tests/onboarding.rs | 81 ++++++++++++++++++- 6 files changed, 266 insertions(+), 54 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 8c206de..38592fd 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -50,6 +50,6 @@ - Roles are not exclusive: a single node may issue queries and answer them concurrently (I5, §3 "any member"). Implement querier/responder as independent enable flags — never an exclusive mode enum or fixed deployment role. - Matching floor: boundary tokenizer (`src/tokenizer.rs` — letter/digit splits so `5555` matches `DLEX5555`, lowercase, ASCII fold, English stopwords+stemmer) → coverage gate (`[match] min_coverage`, default 0.4; 1–2 term queries require all terms) → title boost 2.0 + phrase boost 3.0 + query-time snippets. Schema changes require a fresh index dir (`open_or_create` errors on mismatch). - Engine seam: `src/engine.rs` `SearchEngine` trait (`search` → `EngineOutput { hits, total: Option }`, `doc_count`); `respond()` in `src/node.rs` is the conformance wrapper (budget clamp, truncation from engine total — unknown total forces `truncated = true`). Power users can implement the trait (HTTP adapter or subprocess to an external engine). -- Onboarding: `frxd --onboarding` runs a wizard consuming a credential block (`id=.. token=.. registry=.. ma_key=..`) issued by the MA's signup endpoint (`registry serve --signup-code --registry-url`; HTML page at `/`, `POST /v1/signup` → one-time invite token, `POST /v1/enroll` binds keys and re-signs). Identity registration stays MA-side; the wizard never creates identities, only binds locally generated keys. Invites live in `/invites.json`; the form's organization/representative/contact/payment fields are stored privately in `/applications.json` (mode 600, MA contract data — never in the signed snapshot), and the two acknowledgement checkboxes are required by the endpoint. Prompts accept empty input as the default; scripted stdin works for tests. +- Onboarding: `frxd --onboarding` runs a wizard consuming a credential block (`id=.. token=.. registry=.. ma_key=..`) issued by the MA's signup endpoint (`registry serve --signup-code --registry-url`; HTML page at `/`, `POST /v1/signup` → one-time invite token, `POST /v1/enroll` binds keys and re-signs). Identity registration stays MA-side; the wizard never creates identities, only binds locally generated keys. Signup without a code queues a pending application (`/applications.json`, mode 600, MA contract data — never in the signed snapshot); `frxd registry approve ` promotes it (member stub + invite + credential block). A valid `--signup-code` approves immediately. Invites live in `/invites.json`. Prompts accept empty input as the default; scripted stdin works for tests. - Next matching steps: eval harness with a small golden set (precision@k + false-silence rate), then a dense recall leg (model2vec-rs 0.2.1 exists but needs `default-features = false, features = ["fancy-regex", "local-only"]` for musl/airgapped; verify crate + model licenses before bundling), then an optional cross-encoder reranker. Embeddings are for recall; reranking is the precision tier. - Identity/registry (RFC Draft 0.5 §4/§6): MA-hosted FQDN identifiers first (`