Files
backend/docs/geo-auth-backend-plan.md
Andriy Oblivantsev ba7cd51a84
CI / test (push) Failing after 35s
Upgrade runtime to Go 1.25 and add container orchestration.
Add a cache-optimized multi-stage Dockerfile with non-root runtime, compose service definitions for local/dev execution, CI Go version alignment, and docs/path cleanup updates.

Made-with: Cursor
2026-03-01 11:44:07 +00:00

7.3 KiB

name, overview, todos, isProject
name overview todos isProject
geo-auth-backend-plan Design and implement a Go + PostgreSQL(PostGIS) backend with Ed25519 auth, hybrid invitation onboarding, and per-user GeoJSON feature-collection management; plus a no-build Vue/Vuetify frontend for key lifecycle and API usage.
id content status
bootstrap-go-api Create greenfield Go API skeleton with config, routing, and health endpoints pending
id content status
auth-ed25519 Implement challenge-response auth with Ed25519 verification and token issuance pending
id content status
hybrid-invitations Implement hybrid invitation issuance/verification with lineage and replay protection pending
id content status
geo-storage Add PostGIS-backed models/migrations for collections and point features pending
id content status
geo-crud-endpoints Expose authenticated per-user GeoJSON collection/feature CRUD endpoints pending
id content status
frontend-static-vue Build no-bundler Vue+Vuetify static frontend with key generation/import/export in localStorage pending
id content status
tests-and-hardening Add tests for auth/invites/geo ownership and enforce validation/security checks pending
id content status
ts-api-client-lib Create reusable TypeScript API client library with @noble/ed25519 for key generation, key storage helpers, and signed API communication pending
id content status
js-frontend-wrapper Add plain JavaScript wrapper adapter so no-build frontend can consume the TypeScript-built client bundle pending
false

Geo App Auth + GeoJSON Service Plan

Current Project Context

  • No existing backend source files were found in this repository root, so this plan assumes a greenfield implementation.
  • Stack confirmed: Go + PostgreSQL (+ PostGIS).
  • Invitation model confirmed: Hybrid (signed token + inviter lineage tracking).
  • Client scope confirmed: both a reusable TS library and a plain JS frontend integration.
  • Build policy confirmed: npm/build allowed for library package only; frontend remains no npm/no bundling.

Architecture

  • Auth identity: user identity = Ed25519 public key (base64url); server never stores private keys.
  • Login/auth: wallet-style challenge-response:
    • client requests nonce
    • client signs nonce with private key
    • server verifies signature against registered public key
    • server returns short-lived access token + optional refresh token.
  • Registration via invitation:
    • inviter generates signed invitation payload (invitee pubkey optional at creation time)
    • invite token includes inviter key, expiry, nonce/jti, usage constraints, and lineage metadata
    • invitee submits invite token + own pubkey + signature proof
    • server verifies inviter trust chain + token signature + replay protection.
  • Data model: users own feature collections; each collection owns GeoJSON Features (initially Point geometry).
  • Storage: PostGIS geometry column (geometry(Point, 4326)) plus raw GeoJSON JSONB for roundtrip fidelity.
flowchart TD
  inviter[ExistingUserInviter] -->|"signs invite token"| inviteToken[InviteToken]
  invitee[NewUserInvitee] -->|"submits pubkey + signed challenge + token"| api[GoAPI]
  api -->|"verify inviter + token + signature"| users[(Users)]
  api -->|"issue access token"| session[(Sessions)]
  invitee -->|"CRUD collections/features"| api
  api --> collections[(FeatureCollections)]
  api --> features[(FeaturesPostGIS)]

Planned Files and Components

  • Backend bootstrap:
    • cmd/api/main.go
    • internal/http/routes.go
    • internal/config/config.go
  • Auth/invitation domain:
    • internal/auth/challenge.go
    • internal/auth/ed25519_verify.go
    • internal/invite/token.go
    • internal/invite/service.go
  • Geo domain:
    • internal/geo/collections_service.go
    • internal/geo/features_service.go
  • Database:
    • migrations/0001_init_users_invites.sql
    • migrations/0002_geo_collections_features.sql
  • Frontend (no npm/bundling):
    • web/index.html
    • web/app.js
    • web/api.js
  • Reusable TypeScript client library (separate package):
    • libs/geo-api-client/package.json
    • libs/geo-api-client/tsconfig.json
    • libs/geo-api-client/src/GeoApiClient.ts
    • libs/geo-api-client/src/keys.ts
    • libs/geo-api-client/src/storage.ts
    • libs/geo-api-client/dist/ (build output consumed by frontend)

API Surface (v1)

  • POST /v1/auth/challenge -> nonce
  • POST /v1/auth/login -> verify signature, issue token
  • POST /v1/auth/register -> invite validation + pubkey registration
  • POST /v1/invitations -> inviter creates signed invite payload
  • GET /v1/me/keys -> registered pubkey metadata
  • POST /v1/collections / GET /v1/collections
  • POST /v1/collections/{id}/features / GET /v1/collections/{id}/features
  • PATCH/DELETE /v1/features/{id}

Security and Validation

  • Enforce strict canonical payload format before signature verification.
  • Replay protection with nonce/jti tables and TTL.
  • Invite expiration + max use + optional binding to target pubkey.
  • Per-user row-level authorization in service layer (and optionally DB RLS later).
  • Input validation for GeoJSON (Feature, Point, lon/lat ranges, SRID 4326).

Frontend Constraints Implementation

  • Serve Vue + Vuetify from CDN (no npm, no bundling).
  • Key lifecycle in browser via client library:
    • generate Ed25519 keypair using @noble/ed25519 in TS client
    • precreate key material when first profile/session is initialized
    • store key material in localStorage through client helper API (with optional encryption passphrase layer)
    • import/export profile key material from user settings page.
  • UI pages: Login/Register (invite), Collections list, Mapless Feature editor (Point first), Profile key management.

TypeScript API Client Library Scope

  • Export GeoApiClient class for all API communication:
    • createChallenge(), loginWithSignature(), registerWithInvitation()
    • createInvitation()
    • collection/feature CRUD methods.
  • Export key-management helpers:
    • generateKeyPair(), signChallenge(), exportKeys(), importKeys()
    • ensureKeysInStorage() for precreate-on-first-use behavior.
  • Add request signing conventions compatible with backend challenge/invitation verification.
  • Build to browser-consumable ESM/UMD artifacts; frontend uses built JS file directly without bundling.

TDD-first Delivery Slices

  1. Auth challenge + login signature verification tests.
  2. Invitation token verification + replay/expiry tests.
  3. Registration tests (happy path + invalid inviter chain).
  4. Geo collection ownership tests.
  5. GeoJSON point validation + CRUD tests.
  6. TS client unit tests (@noble/ed25519 flows, storage, API error handling).
  7. Frontend key-management smoke tests (manual + scripted API checks via JS wrapper).

Acceptance Criteria

  • Only registered public keys can authenticate and access their own data.
  • New user registration succeeds only with valid inviter lineage and signed token.
  • Users can create/read/update/delete their own feature collections and Point features as GeoJSON.
  • Reusable TS API client class handles auth + geo API communication and key lifecycle with @noble/ed25519.
  • Frontend runs as static files without build tooling, consuming prebuilt client bundle, and supports key import/export + local persistence.