Files

taco-bot

Tinqs meeting assistant: AWS App Runner + Chrome extension for Google Meet (wake phrase “Hey Taco”, chat prefix 🌮 Taco:). Git Studio: tinqs-ltd/taco-bot.

The in-meeting persona is still Taco (wake phrase “Hey Taco”, chat prefix 🌮 Taco:). This repository's name is taco-bot.

Production domain: https://taco.arikigame.com (Cloudflare CNAME → App Runner, DNS-only).

Architecture

Next.js 16 (App Router) on AWS App Runner (eu-west-1). Docker standalone build. The Chrome extension in extension/ calls:

Route Purpose
GET /api/meeting/status Extension config (selectors, triggers, version)
POST /api/meeting/transcript Append live captions (auth required)
POST /api/meeting/ask Ask Taco (Bedrock Mistral + optional docs search)
GET|POST /api/meeting/calendar Cron placeholder

Backend: AWS Bedrock (Mistral Ministral 8B, set LLM_PROVIDER=claude to switch to Anthropic), Gitea docs search on tinqs-ltd/docs (Git Studio API), in-memory store (Redis planned).

Repository layout

Path Purpose
app/api/meeting/ Next.js route handlers (transcript, ask, status, calendar)
lib/ Shared server code (Claude, GitHub docs search, KV, CORS)
extension/ Chrome extension (Manifest V3) — load unpacked for development
public/ Static files (e.g. taco-status.html)
planning.md Architecture decisions, product vision

Hosting

  • Production URL: https://taco.arikigame.com
  • App Runner URL: https://ytre5eznhp.eu-west-1.awsapprunner.com
  • ECR: 149751500842.dkr.ecr.eu-west-1.amazonaws.com/taco-bot
  • Region: eu-west-1
  • DNS: taco.arikigame.com CNAME (DNS-only) → App Runner. ACM cert for SSL.

Deploy

# Build, push, deploy
docker build --platform linux/amd64 -t taco-bot .
aws ecr get-login-password --region eu-west-1 | docker login --username AWS --password-stdin 149751500842.dkr.ecr.eu-west-1.amazonaws.com
docker tag taco-bot:latest 149751500842.dkr.ecr.eu-west-1.amazonaws.com/taco-bot:latest
docker push 149751500842.dkr.ecr.eu-west-1.amazonaws.com/taco-bot:latest
aws apprunner start-deployment --service-arn "arn:aws:apprunner:eu-west-1:149751500842:service/taco-bot/7825a8030fce4f038e075018d700f489" --region eu-west-1

Full deploy workflow: devops/pipelines/taco-bot-apprunner.md.

Environment variables

Set in App Runner → taco-bot → Configuration → Environment variables.

Variable Required Purpose
LLM_PROVIDER Yes bedrock (default) or claude
TACO_API_SECRET Yes Extension sends Authorization: Bearer … or x-taco-key
GITEA_TOKEN Yes Gitea API token for docs search on Git Studio
GITEA_DOCS_REPO No Default: tinqs-ltd/docs (Git Studio)
AWS_REGION No Default: eu-west-1
BEDROCK_MODEL No Default: mistral.ministral-3-8b-instruct
ANTHROPIC_API_KEY Only if LLM_PROVIDER=claude Deprecated — use Bedrock

Without Redis configured, transcript/rate-limit uses in-memory fallback (fine for dev, not production).

Team access

Jeremy (owner)

  • Git Studio: Push access on tinqs-ltd/taco-bot.
  • AWS: IAM user jeremy with AdministratorAccess. Can deploy via ECR + App Runner CLI.

CTO

Organization Admin. Direct push to main.

Custom domain

taco.arikigame.com — Cloudflare CNAME (DNS-only) → ytre5eznhp.eu-west-1.awsapprunner.com. ACM cert handles SSL. Three ACM validation CNAME records in Cloudflare (added 8 Apr 2026).

Security — Tailscale auth (8 Apr 2026)

This service is protected by Tailscale identity — ported from admin.arikigame. The Next.js middleware (middleware.ts) runs on every request and requires one of:

Auth path How it works
Bearer token Extension sends Authorization: Bearer <TACO_API_SECRET> — works from any network
Tailscale headers tailscale serve injects tailscale-user-login header — tailnet only
Tailscale IP + whois Direct 100.x access → whois proxy resolves to @tinqs.com user — tailnet only
Dev bypass ALLOW_DEV_AUTH=true or NODE_ENV=development — local dev only

Unauthenticated browser requests → redirect to /connect-tailscale (landing page). Unauthenticated API requests → 401 JSON.

For Lightsail deployment (bot.arikigame.com)

All three auth paths work. Set TAILSCALE_WHOIS_PROXY_URL=http://127.0.0.1:8380 to enable IP-based identity resolution.

For App Runner deployment (taco.arikigame.com)

Bearer token is the primary auth path — the extension sends it with every request. Tailscale headers/IP won't be present since App Runner is public internet. Unauthenticated browser hits get the Tailscale required page.

Jeremy — important

The middleware is now active in production. The Chrome extension already sends the Bearer token, so it continues to work. But if you curl the API without -H "Authorization: Bearer $TACO_API_SECRET", you'll get 401. Add the header or set ALLOW_DEV_AUTH=true locally.

Chrome extension

  1. Open chrome://extensions → enable Developer modeLoad unpacked → select this repos extension/ folder.
  2. Click the Taco icon → set Gateway base URL to https://taco.arikigame.com (no trailing slash) → TACO API secret (same as TACO_API_SECRET) → Save.
  3. Use Test connection to verify /api/meeting/status.
  4. Join a Google Meet with captions on. Say “Hey Taco, …” or type “Taco, …” in in-meeting chat.

Permissions: The manifest allows https://*/* so the extension can call your chosen gateway host without a separate build per domain. For production, narrow host_permissions in extension/manifest.json to https://taco.arikigame.com/*.

Local development

npm ci
# create .env.local with your secrets (see env vars table above)
npm run dev

API base: http://localhost:3000/api/meeting/… (dev), http://localhost:5500/… (Docker/prod)

Timeouts: /api/meeting/ask can exceed 10s (Bedrock + Gitea docs search). App Runner has no function timeout limit — the maxDuration in route.ts is a Next.js hint only.