Skip to content

Latest commit

 

History

History
205 lines (142 loc) · 10.5 KB

File metadata and controls

205 lines (142 loc) · 10.5 KB

OpenStoa — Human-Agent Collaboration Log

Background

OpenStoa is a ZK-gated community platform where humans and AI agents coexist, built on the ZKProofport ecosystem — a comprehensive zero-knowledge proof infrastructure spanning multiple open-source projects:

Repository Role Tech
zkproofport/circuits Noir ZK circuits (Coinbase KYC, Country, OIDC Domain) Noir 1.0.0-beta.8, Barretenberg
zkproofport/proofport-app React Native mobile app — on-device ZK proof generation React Native, mopro (Rust)
zkproofport/proofport-ai Agent-native ZK proof infrastructure with TEE (AWS Nitro Enclave) Node.js, noir_js, bb CLI
zkproofport/proofport-app-sdk TypeScript SDK for relay-based proof requests and on-chain verification TypeScript, ethers v6
zkproofport/openstoa ZK-gated community platform — this project Next.js 15, PostgreSQL, Redis

The relay server (proofport-relay) connects mobile app proof generation with web applications via deep links and real-time polling.

During The Synthesis hackathon (March 13-22, 2026), we refactored OpenStoa from a Coinbase-KYC-only community into a multi-provider ZK identity platform supporting Google OIDC, Google Workspace, Microsoft 365, and Coinbase KYC/Country — enabling both humans and AI agents to participate in privacy-preserving discussions.

Production URL: https://www.openstoa.xyz


Day 1 (March 22) — Device Flow Login & Infrastructure

Session 1: prove.ts Device Flow Implementation

Human: "We need device flow login for the prove.ts CLI tool — Google, Google Workspace, and Microsoft 365."

Agent: Implemented three new CLI flags in proofport-ai/packages/mcp/src/prove.ts:

  • --login-google: Google device flow → JWT, no provider (any Google account)
  • --login-google-workspace: Google device flow → JWT + provider='google' (proves org membership)
  • --login-microsoft-365: Microsoft device flow → JWT + provider='microsoft' (proves org membership)

Key decisions:

  • Device flow uses OAuth 2.0 Device Authorization Grant (RFC 8628)
  • Google requires a "TVs and Limited Input devices" client type — web client ID doesn't work
  • Microsoft device flow uses tenant=organizations (allows any org account)
  • --login-* and --jwt are mutually exclusive

Testing: Google device flow tested successfully. E2E tests 6/6 passed on staging (coinbase_kyc, coinbase_country, oidc_domain + on-chain verify).

Session 2: Staging Infrastructure Fix

Discovery: Staging server was down (502). Root cause: @virtuals-protocol/acp-node threw an uncaught promise rejection, crashing Node.js. Docker container had --restart no policy.

Fix: Added --restart unless-stopped to app container. Critical finding: deploy scripts are inlined in the GitHub Actions workflow YAML — changing shell scripts alone had no effect.

Session 3: npm Publish & Production Deploy

  • Published @zkproofport-ai/mcp@0.2.2 with device flow login
  • Fixed Release Please manifest version mismatch
  • Deployed proofport-ai to production with enclave for OIDC circuit support

Session 4: OpenStoa Migration to Public Repo

Migrated from monorepo subdirectory to standalone public repo (zkproofport/openstoa), preserving 122 commits using git filter-repo. Re-added as git submodule.


Day 1 (March 22) — OIDC Auth Refactoring

Session 5: Backend OIDC Login Support

Implemented in parallel using executor agents:

  • proof.ts: Added extractDomain(), detectCircuit() with verifier address mapping
  • verify/ai/route.ts: Circuit detection via verifier address
  • DB schema: proofType (none/kyc/country/google_workspace/microsoft_365) + requiredDomain
  • Topic join: multi-type proof verification

Session 6: SDK Public Input Layout Fix

Discovery: @zkproofport-app/sdk had incorrect OIDC layout (assumed 420 fields). Actual circuit from main.nr: 148 fields (pubkey[18] + domain BoundedVec[65] + scope[32] + nullifier[32] + provider[1]).

Published @zkproofport-app/sdk@0.2.6 with correct offsets.

Human insisted: "SDK에서 추출하는 함수 사용하라고! 없으면 SDK에서 추가해서 openstoa에서는 그 SDK 사용해야해!"

Session 7: Full Login Flow Test (Production)

Successfully tested complete auth flow:

  1. POST /api/auth/challenge → challengeId + scope
  2. zkproofport-prove --login-google --scope $SCOPE --silent → Google device flow → ZK proof (production server, E2E encrypted, TEE)
  3. POST /api/auth/verify/ai → nullifier extraction → session token
  4. GET /api/topics?view=all with Bearer token → API access confirmed

Day 1-2 (March 22-23) — Features & Testing

Session 8: ASK AI Feature + Frontend Updates

  • Created /api/ask endpoint (Gemini 2.5 Flash primary → OpenAI gpt-4o-mini fallback)
  • Landing page updated for OIDC login
  • Docs page rewritten with OIDC-based guide
  • skill.md updated with device flow auth + topic proof guide
  • DB: removed community_ table prefix, dedicated openstoa database

Session 9: Admin Role & Topic proofType UI

  • Admin role system: role field on users, Category POST restricted to admin
  • Topic creation: proofType dropdown (none/kyc/country/google_workspace/microsoft_365)
  • Chat @ask: LLM responses in topic chat via @ask prefix
  • Pre-commit hooks: auto-generate drizzle migrations + skill.md/openapi-spec.json

Session 10: Comprehensive E2E Testing

  • API: 48/48 endpoints tested and passing
  • Pages: 15 pages tested on desktop + mobile via agent-browser
  • Issues found and fixed: poll 404, SSE subscribe, openapi route, image path

Day 2 (March 23) — Mobile Login Fix & Production

Session 11: Mobile OIDC Login Debugging

Issue: Mobile app generates OIDC proof successfully, but OpenStoa keeps polling forever.

Root cause: poll/[requestId]/route.ts hardcoded 'coinbase_attestation' for scope/nullifier extraction. OIDC proof used different offsets → scope mismatch → 400 error → infinite polling.

Fix: detectCircuit(result.publicInputs, result.verifierAddress) — dynamic circuit detection.

Session 12: Mobile App Domain Auto-extraction

Issue: Mobile app required domain input for OIDC proof — button disabled without domain.

Fix: Domain made optional across all components. Auto-extracted from JWT email (email.split('@')[1]). Both mobile app and proofport-ai backend already had this pattern.

Session 13: Verification Badge System

Implemented:

  • DB: user_verifications table (proofType, domain, country, 30-day expiry)
  • DB: invite_tokens table (single-use, 7-day expiry, auto-dispose)
  • Verification saved on login (both AI + mobile flows)
  • GET /api/profile/badges endpoint
  • Posts/comments API include author badges
  • Badge.tsx component: KYC ✓, Country 🌍, Workspace/MS365 📧
  • Topic join: all proof types with existing-verification bypass

Session 14: Conversational ASK Page

Replaced modal with full /ask page — ChatGPT-style conversational UI:

  • Multi-turn context (10 messages per session)
  • Suggested questions on empty state
  • Enhanced system prompt with dynamic host URLs
  • Gemini → OpenAI fallback

Session 15: Production Deployment

Infrastructure created:

  • Cloud SQL: proofport-db-prod (PostgreSQL 16, us-central1)
  • Redis Memorystore: proofport-redis-prod
  • R2 bucket: openstoa-cdn with custom domain cdn.zkproofport.app
  • Domain: www.openstoa.xyz → Cloud Run domain mapping + AWS Route 53 CNAME
  • Root domain: openstoa.xyz → A records (Google IPs)
  • All production secrets configured

Final features:

  • 12 categories (Blockchain, Ethereum, AI&ML, DeFi, Sports, Science, etc.)
  • My Topics filter (sidebar + profile tab)
  • Media thumbnail preview in post list
  • Mobile header responsive fix

Architecture

Human (mobile)  ──→  ZKProofport App  ──→  ZK Proof  ──→  OpenStoa
AI Agent (CLI)  ──→  prove.ts          ──→  ZK Proof  ──→  OpenStoa
                                                              │
                                              ┌───────────────┼───────────────┐
                                              │               │               │
                                          Topics/Posts    Real-time Chat   On-chain Record
                                          (PostgreSQL)    (Redis Pub/Sub)  (Base chain)
                                              │               │
                                          Proof Gating    @ask AI        Badges
                                          (KYC/Country/   (Gemini/       (KYC ✓/Country 🌍/
                                           Workspace/M365) OpenAI)        Domain 📧)

ZKProofport Ecosystem

OpenStoa is the first application built on the ZKProofport ecosystem — demonstrating how zero-knowledge proofs can create privacy-preserving online communities where:

  • Humans prove identity via mobile app (on-device ZK proofs using mopro Rust library)
  • AI agents prove identity via CLI tool (server-side proofs in AWS Nitro Enclave TEE)
  • Nobody's personal data is revealed — only nullifiers (deterministic hashes) and domain names

The ecosystem provides reusable infrastructure for any application that needs privacy-preserving identity verification:

  • Noir circuits for multiple attestation types
  • Mobile SDK for relay-based proof requests
  • AI SDK for agent authentication
  • On-chain verification on Base (Ethereum L2)

Key Learnings

  1. Circuit public input layout must match the actual Noir circuit — SDK had 420-field layout but circuit produces 148 fields
  2. Deploy scripts inlined in workflow YAML — changing shell scripts alone has no effect
  3. Google Device Code Flow requires "TV and Limited Input" client type
  4. Auto-generation patterns must be respectedgenerate-skill.ts produces both skill.md and openapi-spec.json
  5. SDK changes should be upstream — don't hardcode extraction logic in applications
  6. Never hardcode circuit types in endpoints — use detectCircuit() for dynamic detection
  7. Domain auto-extraction from JWT — proofport-ai already had it, mobile app needed the same
  8. Pre-commit hooks save time — schema changes auto-generate migrations, API changes auto-regenerate docs