---
id: TASK-79
title: Fix guardian invitation acceptance — server-initiated WebAuthn flow
status: Done
assignee: []
created_date: '2026-03-03 00:56'
labels:
  - bugfix
  - encryptid
  - webauthn
dependencies: []
priority: high
---

## Description

<!-- SECTION:DESCRIPTION:BEGIN -->
Guardian invitation acceptance and auth.rspace.online login were broken. The guardian page and main login page used the client-side SDK's `authenticatePasskey()`/`registerPasskey()` which generate their own challenge, then tried to send `result.challenge` and `result.credential` to the server — but `AuthenticationResult` doesn't have those properties (both undefined). The postgres driver threw `UNDEFINED_VALUE` on `getChallenge(undefined)`, resulting in a raw 500 "Internal Server Error" that the client couldn't parse as JSON.

Fixed by replacing with the proper server-initiated flow (matching rstack-identity.ts): `/api/auth/start` → WebAuthn → `/api/auth/complete`, and same for registration. Also fixed Dockerfile.encryptid to include `shared/local-first/` in the build context (needed by login-button.ts importing encryptid-bridge).
<!-- SECTION:DESCRIPTION:END -->

## Acceptance Criteria
<!-- AC:BEGIN -->
- [ ] #1 Guardian invitation acceptance completes without JSON parse error
- [ ] #2 auth.rspace.online login/register works with server-initiated WebAuthn
- [ ] #3 Dockerfile.encryptid builds successfully with shared/local-first context
<!-- AC:END -->

## Final Summary

<!-- SECTION:FINAL_SUMMARY:BEGIN -->
Fixed 500 error on guardian invitation acceptance caused by client sending `undefined` challenge/credential to server.

**Root cause:** Guardian page and auth.rspace.online login used client-side SDK functions (`authenticatePasskey()`/`registerPasskey()`) which return `AuthenticationResult` — but code referenced `.challenge` and `.credential` properties that don't exist on that type. Both were `undefined`, causing postgres `UNDEFINED_VALUE` error → 500 plain text → client JSON parse failure.

**Fix:** Replaced with server-initiated WebAuthn flow matching `rstack-identity.ts`:
1. `POST /api/auth/start` → get server challenge
2. `navigator.credentials.get()` with that challenge
3. `POST /api/auth/complete` with `{ challenge, credential: { credentialId } }`

Also fixed `Dockerfile.encryptid` to COPY `shared/local-first/` (needed by `login-button.ts` → `encryptid-bridge.ts`).

Commits: 88118cd (WebAuthn flow), 4dd212e (Dockerfile fix). Both rspace-online and encryptid containers rebuilt and deployed.
<!-- SECTION:FINAL_SUMMARY:END -->
