Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,48 @@ VERCEL_OIDC_TOKEN=
# AI Gateway is normally authenticated by Vercel OIDC. Set an explicit key only outside that flow.
AI_GATEWAY_API_KEY=

# Project V2 private storage and project-data capability signing.
# PROJECT_DATA_CAPABILITY_SECRET must be 32+ bytes, but does not by itself enable Project Data:
# production still needs an injected durable adapter and trusted capability issuer.
PROJECT_DATA_CAPABILITY_SECRET=
# Set these to "1" only for non-production process-memory proof mode.
DROPS_STUDIO_LOCAL_PROJECT_STORE=
DROPS_STUDIO_LOCAL_PROJECT_DATA=

# Production Sandbox authentication uses Vercel OIDC and needs none of these explicit values.
# For local Sandbox authentication only, set VERCEL_TOKEN, VERCEL_PROJECT_ID, and
# VERCEL_TEAM_ID together; never configure only part of that local credential trio.
# VERCEL_TEAM_ID has one additional production use: set it only when the server-owned
# generated-app deployment project below belongs to a Vercel team. Personal scope omits it.
VERCEL_TOKEN=
VERCEL_PROJECT_ID=
VERCEL_TEAM_ID=

# Server-only prebuilt browser-check snapshot created with @agent-browser/sandbox.
AGENT_BROWSER_SNAPSHOT_ID=

# Vercel Cron authenticates scheduled idle cleanup with this 32+ character server secret.
CRON_SECRET=
# Optional integer from 5 through 240; defaults to 20 minutes.
DROPS_STUDIO_SANDBOX_IDLE_MINUTES=
# Set to "1" only to opt into the live Sandbox contract test.
DROPS_STUDIO_LIVE_SANDBOX=
# Set to "1" only to opt into the full live install/build/preview/browser/checkpoint flow.
DROPS_STUDIO_LIVE_BUILDER=

# GitHub App is preferred for least-privilege branch/commit/PR integration.
GITHUB_APP_ID=
GITHUB_APP_PRIVATE_KEY=
GITHUB_APP_INSTALLATION_ID=
# Comma-separated exact owner/repository allowlist for platform App credentials.
GITHUB_APP_ALLOWED_REPOSITORIES=
# Visitor GitHub access tokens are tab-scoped and sent request-only; there is no token env name.

# Generated-app preview deployment. Visitor tokens remain tab-scoped/request-only.
# These optional platform values never enter generated source or Sandbox environment.
VERCEL_DEPLOY_TOKEN=
VERCEL_GENERATED_PROJECT_ID=

# Stripe Billing and signed team collaboration. Values are configured only in the provider environment.
STRIPE_SECRET_KEY=
STRIPE_WEBHOOK_SECRET=
Expand Down
73 changes: 73 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,76 @@ Report exact failures. Never update baselines or skip a gate automatically.
- Never print `.env*` values or user/provider secrets.
- Commit and push intentional completed work; deploy only after all release gates pass.

## V2 Sandbox Builder workstream

These rules apply whenever work targets Project V2, the AI builder loop, or
persistent Vercel Sandbox previews.

### Full repository and release authority

- Before planning, inspect `git status -sb`, `git branch -vv`, `git worktree list`, recent commits, open PRs, and the latest default-branch CI so every mutation starts from verified current state.
- `codex/drops-studio-v2-sandbox-builder` is the prepared starting worktree, not an access boundary. The lead may inspect, create, switch, repair, or retire any Drops Studio branch or worktree needed to complete the product.
- The lead has full read/write/admin and release authority across the complete Drops Studio surface: `main`, every branch and worktree, historical and active PRs/issues, GitHub Actions and repository settings, Vercel project settings and environment variables, previews, production deployments, domains and aliases, Drops Studio VPS/runtime/services/storage, Sandbox resources, provider configuration, and product integrations.
- Commit, push, fetch, rebase, cherry-pick, merge, close or supersede PRs, update `main`, deploy, promote, roll back, and change the production alias when useful to finish or recover the product. These operations do not require another approval within the Drops Studio task.
- Historical PR #1 and PR #2 are normal repository history, not protected read-only state. Reuse, supersede, close, or modify their remaining branches when the verified current architecture benefits.
- Access includes reading and updating protected provider or deployment configuration through their proper interfaces. Never print secrets, place them in source/generated files/logs, or commit them.
- Preserve V1 projects, all 12 recipes, `/p/{slug}`, ZIP export, current connections, checkpoints, and session-only BYOK behavior as product outcomes. Migrate or replace internals when necessary, but verify compatibility before release.
- `/opt/coldmath`, ColdMath services, and the ColdMath repository remain outside this task because they are a separate product. Using the saved ColdMath VPS host as the task entry point does not authorize ColdMath changes.

### Work-package ownership

- The lead owns sequencing, shared contracts, cross-package integration, dependency manifests and lockfiles, final git operations, PR creation, and preview deployment.
- Project model owns versioned schemas, path and file validation, deterministic hashes, migration, templates, diffs, checkpoints, and persistence.
- Runtime owns `ProjectRuntimeAdapter`, Vercel Sandbox lifecycle, processes, ports, logs, limits, cleanup, network policy, and runtime audit evidence.
- Agent loop owns AI SDK orchestration, strict tool schemas, permissions, approvals, bounded outputs, repair limits, and request-only provider access.
- Studio owns the current unified workspace UI, real file/editor/preview/log/history states, Storybook, accessibility, and browser flows. It must not restore obsolete panels.
- Crypto integrations own typed DropsTab and Drops Bot proxies, provider evidence, fixtures, Telegram boundaries, and truthful unavailable or setup-required states.
- QA/release owns adversarial tests, CI parity, preview verification, and the final evidence table. It cannot waive a failing gate.
- Parallel agents normally receive disjoint files. The lead coordinates shared types, configs, manifests, integration points, and may explicitly delegate branch, commit, push, PR, deployment, or production operations when that accelerates delivery without creating conflicting ownership.

### Plugin-first workflow

- Read every applicable `SKILL.md` completely before task actions.
- Use `agyb-essentials:concise-planning` for the implementation graph and context-mode for the long-running execution when callable.
- Use `vercel:vercel-sandbox`, `vercel:ai-sdk`, `vercel:ai-gateway`, `vercel:nextjs`, `vercel:deployments-cicd`, and `vercel:verification` for runtime, deployment, and agent work.
- Use `build-web-apps:frontend-app-builder`, `build-web-apps:frontend-testing-debugging`, `build-web-apps:react-best-practices`, `build-web-apps:shadcn`, and relevant `agyb-aas-web-app-builder` skills for Studio implementation.
- Use `product-design:index` and `product-design:audit` for visible UX; use Creative Production intake/produce for reference-driven final design QA.
- Use Playwright MCP or repository Playwright for every rendered or interactive change. Its global output directory must remain Drops-specific and must never point at a ColdMath workspace.
- Use `github:github`, `github:gh-fix-ci`, and `github:yeet` or verified `gh` fallback for repository operations.
- Use CodeRabbit after the bounded local gate with `coderabbit review --agent --base main`; verify every finding before editing and never weaken tests to satisfy it.
- Use OpenAI Developers only for OpenAI API work. Use Sites only for `.openai/hosting.json` or an explicitly requested secondary preview. Use Remotion only for actual video output and Visualize only when a diagram or data visualization materially helps.
- Do not invoke unrelated skills merely to claim plugin usage.

### Runtime and security boundary

- Multi-file source is canonical for Project V2; `GeneratedProjectSpec` remains product metadata. Preserve independently versioned store, workspace, spec, and provider-record envelopes.
- Untrusted build, install, test, server, and command execution occurs only in Vercel Sandbox. Browser-safe legacy preview may continue in its sandboxed iframe, and published deployments execute on their declared host.
- `run_command` is a policy-validated argv or declared-task tool, never a free-form host shell. `install_package` accepts exact public-registry versions, keeps lifecycle scripts disabled, and records an audit event.
- No provider or platform secret may enter generated files, Sandbox environment or filesystem, logs, checkpoints, Blob snapshots, ZIPs, prompts, or tool output.
- Every external or destructive tool has explicit approval, timeout, quota, audit record, bounded output, and idempotency behavior.
- DropsTab quota-bearing tests use fixtures and cache boundaries. Live Sandbox or provider smoke tests run only behind explicit flags and never use production user accounts implicitly.
- Never promote preview or browser telemetry into provider evidence.

### Validation and production release

- Reproduce inherited default-branch failures before feature work. Fix their root cause without changing visual baselines or weakening thresholds.
- During implementation run narrow owner-specific tests. Run the full CI-equivalent gate once at the final boundary:

```bash
npm audit --omit=dev --audit-level=high
npm run guardrails:ui
npm run lint
npm run typecheck
npm run build:vercel
npm run test:unit
npm run build-storybook
npm run test:storybook
npm run test:storybook:visual
npm run test:e2e:prepared
npm run test:lighthouse:prepared
npm run build
```

- Visual baselines, thresholds, fixtures, and test configuration are editable when an intentional product change requires it; document the reason and never use the change to conceal a regression. Do not consume live DropsTab quota in routine tests.
- After the bounded gates, choose and execute the complete release path needed for the task: commit and push, open/update/merge PRs, update `main`, deploy or promote the verified Vercel build, change the production alias, configure runtime resources, and verify the public product.
- Record the before/after Git, CI, deployment, alias, migration, and smoke-test evidence. Maintain a tested rollback path, but do not stop at a preview when a production release is required to complete the product.
20 changes: 20 additions & 0 deletions DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,26 @@ The current rebuilt product architecture is the source of truth. Do not restore

The older `docs/design/project-studio-spec.png` and `docs/screenshots/*` files are historical evidence only. They are explicitly forbidden as new visual baselines. Current-state references define architecture; the accessibility and readability rules below intentionally change their undersized text.

### Project V2 capability references

The user-provided ten-screen pack under `docs/design/v2-reference/` is the
approved capability and visual-polish direction for the V2 builder. Its screen
map and SHA-256 manifest live in `docs/design/v2-reference/README.md`.

- Apply its calm white/blue hierarchy, compact developer-tool affordances,
explicit build stages, real file tree, device preview, logs, checkpoint diff,
integration evidence, and release receipts to the current product.
- Treat every provider badge and status in the pack as a layout reference only.
Drops Studio may render `Live`, `Connected`, `Passed`, `Deployed`, or a real
URL only after the corresponding Sandbox, Drops, GitHub, or Vercel response
has been verified.
- The current prompt-first homepage and unified Project Studio architecture
still control layout. Do not recreate a permanent right Director column,
obsolete four-column shell, or permanent publish sidebar from a concept.
- Use DropsTab market intelligence, Drops Bot monitoring/delivery, the existing
twelve recipes, and honest setup-required states wherever a generic concept
uses interchangeable DeFi or third-party examples.

## Drops Studio brand profile

Brand tokens live only in `app/styles/drops-studio.tokens.css`.
Expand Down
17 changes: 14 additions & 3 deletions app/api/access/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,25 @@ import { readRequestLimitState } from "../../../lib/request-rate-limit.ts";

export const runtime = "nodejs";

function requestOidcToken(request: NextRequest): string | undefined {
const value = request.headers.get("x-vercel-oidc-token")?.trim() ?? "";
return value && value.length <= 4_096 && !/[\r\n\0]/.test(value)
? value
: undefined;
}

export async function GET(request: NextRequest) {
const oidcToken = requestOidcToken(request);
const readinessEnvironment = oidcToken
? { ...process.env, VERCEL_OIDC_TOKEN: oidcToken }
: process.env;
const date = new Date().toISOString().slice(0, 10);
const account = resolveStudioAccount(request.cookies.get(STUDIO_ACCOUNT_COOKIE)?.value);
if (account) {
const fundedQuota = await resolveFundedBuildQuota({ kind: "account", account });
const memberTier = fundedQuota.tier;
const memberLimit = fundedQuota.limit;
const readiness = platformAiReadiness("member");
const readiness = platformAiReadiness("member", readinessEnvironment);
const quota = readiness.available
? await readRequestLimitState({
identity: account.identity,
Expand All @@ -37,7 +48,7 @@ export async function GET(request: NextRequest) {
tier: platformAvailable ? memberTier : "fallback",
used: quota.count ?? 0,
account,
projectSyncAvailable: memberProjectSyncReadiness(),
projectSyncAvailable: memberProjectSyncReadiness(readinessEnvironment),
platformLimit: memberLimit,
}),
quotaSigningConfigured: readiness.signingConfigured,
Expand All @@ -50,7 +61,7 @@ export async function GET(request: NextRequest) {
usageCookie: request.cookies.get(GUEST_USAGE_COOKIE)?.value,
date,
});
const readiness = platformAiReadiness("guest");
const readiness = platformAiReadiness("guest", readinessEnvironment);
const access = accessMetadata({
tier: context.configured && readiness.available ? "guest" : "fallback",
used: context.used,
Expand Down
Loading
Loading