Skip to content

Partner registry and admin endpoint #537

@aram356

Description

@aram356

Parent epic

#532

Description

Implement PartnerRecord, PartnerStore, and the admin registration endpoint that operators use to onboard ID sync partners.

Scope: ec/partner.rs, ec/admin.rs, router update

Acceptance criteria

  • PartnerRecord contains all fields from §13.1 including pull_sync_allowed_domains and batch_rate_limit.
  • PartnerStore::get(), upsert(), find_by_api_key_hash() operate on partner_store KV. upsert() returns Result<bool, ...> (true = created, false = updated).
  • Secondary indexes: apikey:{hash} → partner_id for batch auth, _pull_enabled → [partner_ids] for pull sync. Best-effort, not atomic. Old API key index deleted on key rotation.
  • pull_enabled_partners() re-checks pull_sync_enabled == true on fetched records (stale index guard).
  • API key stored as SHA-256 hex; plaintext never written to KV. verify_api_key() uses constant-time comparison.
  • POST /admin/partners/register validates Authorization: Bearer <token> in-handler against settings.ec.admin_token_hash. Returns 401 before reading body if invalid.
  • Validates: required fields, id format (^[a-z0-9_-]{1,32}$), reserved names, pull_sync_url + ts_pull_token required when pull_sync_enabled, pull_sync_url domain in allowlist.
  • Returns 201 Created on new partner, 200 OK on update, with explicit response DTO (never serialize full PartnerRecord). 400 on validation failure, 503 on KV failure.
  • /admin/partners/register NOT added to Settings::ADMIN_ENDPOINTS. Admin-route-scan test updated with exclusion list. [[handlers]] pattern narrowed from ^/admin to ^/admin/keys.

Spec ref

docs/internal/ssc_technical_spec.md §13

Metadata

Metadata

Labels

No labels
No labels

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions