Turbot/Docs

Turbot documentation

An authenticated companion archive, before live conversation

Turbot provides Supabase OAuth, a gated dashboard, and transactional companion-archive import/export through web and CLI. Live AI character conversation remains unimplemented. The separate iOS repository is a legacy snapshot.

What the web shell carries#

  • Google and GitHub sign-in through Supabase Auth
  • Same-origin OAuth code exchange
  • Session refresh and a signed-out redirect for the dashboard
  • Server-side identity check and sign-out action
  • A first-run walkthrough, replayable from the dashboard account panel
  • Authenticated companion-archive import/export from first run and the dashboard
  • Profiles, personas, characters, conversations, ordered messages, timestamps, prompts, and bounded metadata retained under row-level security

What it does not carry#

  • Live AI character chat or message generation
  • Entitlements, organizations, moderation, or rate limits
  • Payments, subscriptions, terms, or privacy routes
  • Analytics, logs, account deletion, or archive-to-live-chat activation

Web quick start#

Use Node.js 20.9 or newer and a non-production Supabase project with Google or GitHub enabled. Allowlist http://localhost:3000/auth/callback in Supabase and in each OAuth provider application.

shell
git clone https://github.com/wisent-ai/turbot-web.git
cd turbot-web
npm install

NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-publishable-anon-key
SUPABASE_SERVICE_ROLE_KEY=your-server-only-service-role-key

# Apply supabase/migrations/20260905000000_create_companion_archive.sql
npm run dev

Web interfaces#

Routes
RoutePurpose
GET /Public Turbot landing page and entry point to sign-in.
GET /loginStarts Google or GitHub OAuth through the configured Supabase project.
GET /auth/callbackExchanges the provider code for a Supabase session and returns to the same origin.
GET /dashboardServer-checked signed-in placeholder with identity greeting and sign-out.
GET /api/companion-archiveExport the signed-in account's retained companion archive.
POST /api/companion-archiveValidate and transactionally import one companion-archive v1 document.

Companion archive: web and CLI#

On first run, choose Import archive or continue empty. The same reusable control remains on the dashboard under Companion data, beside Export archive. Accepted JSON has format companion-archive, version 1, source product/account identity, profiles/personas, characters, conversations, and sequential user/assistant messages. An archive is refused for its shape, never its size: no file, field, list or nesting limit applies.

Every field, timestamp, source ID, role, position, and relationship is validated before mutation. Source product plus source ID is the durable identity: exact repeats are unchanged, changed identities are conflicts, and existing rows win. The service-role RPC performs one transaction, so invalid input or storage failure leaves no partial rows. Import reports imported/unchanged/conflicting/rejected counts without returning content.

shell
# TURBOT_API_URL requires a bare origin; HTTPS except loopback
export TURBOT_API_URL=https://<turbot-origin>
skarbiec get <item> --field token | npm run archive -- import ./archive.json
skarbiec get <item> --field token | npm run archive -- export ./turbot-export.json

Security and data boundaries#

NEXT_PUBLIC_SUPABASE_URL and NEXT_PUBLIC_SUPABASE_ANON_KEY are intentionally browser-visible. SUPABASE_SERVICE_ROLE_KEY is server-only and is used solely to execute the authenticated transaction RPC; never expose it under NEXT_PUBLIC_*.

Identity/session records and companion archive rows live in Supabase. Row Level Security exposes only the signed-in user's rows. Direct client writes are not granted; both GUI and CLI pass through the strict product API.

If either public Supabase variable is absent, the middleware currently returns without enforcing the dashboard gate. Treat a deployment with missing configuration as unsafe. Missing service-role configuration explicitly refuses import.

Legacy iOS snapshot#

turbot-ios (github.com/wisent-ai/turbot-ios) is an archived SwiftUI application extracted from wisent-ios-old. Its source lives under Wisent/ and its checked-in Xcode project is Wisent.xcodeproj. The current project declares only the app target; it does not contain a native test target.

Open the project with Xcode 16 or newer and select an iOS 17 or newer simulator or device. The bundle identifier, signing team, and API endpoints are legacy values and likely require review before the snapshot can build or connect in a fresh environment. It has no compatibility or release relationship with the current Turbot web shell.

Non-subscribers need an explicit nonnegative free_credits allocation in the current RevenueCat offering. Missing or malformed allocation, missing offering, and failed offering fetch refuse generation rather than granting unlimited access. Active subscribers retain their existing path. Messages presents the cause and a Refresh offering action; first sign-in waits for generation and retains failures instead of completing early. These client checks do not establish backend quota enforcement.

Operations and support#

  • The operator owns the Supabase project, OAuth applications, redirect allowlists, hosting, legal surfaces, and service costs.
  • Configuration changes require a development-server restart or a new deployment; there is no runtime reload.
  • There is no published release or compatibility promise. Turbot Web is private source at package version 0.1.0.
  • Report reproducible web defects in the Turbot Web GitHub issue tracker. Report security issues privately to Wisent maintainers.