Skip to content

AI Des2WF — Infrastructure

Des2WF's own deployment surface. The shared platform infrastructure is documented in Infrastructure.


Compute

Item Value
Runtime Python 3.12 on AWS Lambda, container image
App apps/des2wf — a peer Lambda to apps/wf2des, not a run family inside it
Batching SQS with ReportBatchItemFailures, partial-batch semantics
Shared code packages/figma-ir — imported one-way by both apps, never the reverse

Why a second Lambda rather than a second run family. The WF2Des generation module is ~2,700 LOC with five inline post-passes and a measurably non-deterministic selection path — three runs of one screen produced three distinct specs. Des2WF's engine shares none of that machinery, so putting it in the same module inherits the guard pile and buys nothing. Isolation is the reason, not deploy hygiene.


Queues and triggers

Trigger Owner Des2WF's use
DES2WF queue backend Dedicated transport for generation and post-terminal review; messages retain edge=des2wf, review also carries kind=render_review
wf2des-events intake queue AI side reused for plugin-originated events; the backend holds send permission only
EventBridge schedule AI side none for des2wf. There is no periodic sweep to run: the WF component library is registered on demand from the plugin

Job IDs are shared through the PostgreSQL wf2des table, not through a shared queue. The backend routes queueType=des2wf to SQS_DES2WF_QUEUE_URL; the worker distinguishes generation from review using kind. Kit registration still uses the shared events path.


Storage and secrets

Item Value
Result bucket backend-owned AI bucket, prefix {org}/{proj}/des2wf/
Snapshot storage the full per-node REST envelope, maps retained
DocumentDB guinness_v2; see Stores for result, kit, shared and scoped-override collections
Figma access split by who initiates the work — see below

Two credentials, split by initiator. A snapshot taken with an authority unrelated to the requester lets a user trigger a file they cannot open, and 404s on files the user CAN open when the service account is not a member — both measured on real files, which is why no service-account PAT exists on this path. The split:

Path Credential
Design-snapshot capture (a user action, backend-side) the requesting user's own PAT from the platform figma_token table
Worker-side Figma reads (registration sweep — no user on that path) the org's private OAuth app grant (Authorization: Bearer), stored encrypted in figma_oauth_grant with an AI-owned key; figma_pat env as fallback for a deploy without the app configured

The two credentials have different reachability, so a failure on one path is not evidence about the other, and the error must say which credential was used.


Environment

Variable / config Description
DOCUMENTDB_CONNECTION_STRING, DOCUMENTDB_NAME, DOCUMENTDB_CA_PATH DocumentDB access, guinness_v2
per-collection names env-overridable, including the new wireframe_component
SQS_DES2WF_QUEUE_URL Backend setting for the dedicated generation/review queue
wf2des-events queue URL AI-owned intake
WEBHOOK_BASE_URL, WEBHOOK_API_KEY ai-status endpoint and its X-API-Key
result bucket + key prefix {org}/{proj}/des2wf/
FIGMA_OAUTH_* + grant encryption key worker-side Figma auth — the OAuth app grant (client id/secret live backend-side; the worker holds the AI-owned encryption key and only ever refreshes). figma_pat remains as fallback
snapshot byte cap 20 MB default, env-overridable; enforced on the des2wf capture path — wf2des has no such gate
DEFAULT_ORGANIZATION_ID single-tenant default
model tiers Parse is deterministic. Both modes use the configured strong model for contextual graphic classification when source PNG evidence is available; kit also performs sampled variant selection. Post-render review is a separate vision call. Record model and prompt versions; neither mode guarantees repeat-run identity
PROMPT_VERSION, SPEC_VERSION pinned. Note nothing in the system compares SPEC_VERSION, so it is traceability, not a safety gate

Graphic-classification runtime

  • STRONG_MODEL supplies the vision model; its provider credentials must be available to the worker.
  • DES2WF_VERDICT_TABLE_NAME retains the default collection name des2wf_verdict, but generation reads only scoped record_type=graphic_override_v1 records, not legacy verdicts.
  • Source evidence is an optional S3 PNG captured backend-side with the requesting user's PAT, pinned to the JSON snapshot's Figma version and absolute bounds. The worker reads S3; it does not use its own Figma credentials to recapture generation evidence.
  • Source PNGs are content-addressed by source and render hashes. Review PNGs are separate per-job objects; see Stores.
  • Current classification constants: 6 candidates/batch, 3 concurrent calls, 180 seconds, maximum 32,000,000 source pixels. These are classification limits, not an end-to-end job timeout.
  • Source PNG downloads also have a 20 MiB byte cap. The 20 MB snapshot cap is separate from the PNG pixel cap. Invalid images, unavailable providers and exhausted classification budgets preserve artwork and record a fallback; they do not require the whole generation to fail.
  • Structured logs and graphic_classification distinguish completed, partial and fallback classification. A completed generation alone does not imply every candidate was classified.

Deploy ordering

Order matters here for a reason that has already bitten this project once: a route that acks on enqueue will DLQ envelopes while the client shows success.

  1. Migration first — the edge column, source_node_id, and the recreated partial unique index.
  2. Worker before backend — the worker must be able to consume edge=des2wf before anything can send it.
  3. Backend before plugin — the plugin's des2wf control must not be reachable before the endpoints answer.
  4. events widening as one change across three repos — the plugin field, the backend enum and the internal-api literal ship together, or the MVP's own score cannot reach the server.

CI

Mirrors the WF2Des workflow: lint, type-check, unit and component tests, container build, deploy on merge. Two additions specific to this build:

  • the shared package lands behind re-export shims so the existing suite is untouched on day one; the shim-deletion commit is separate and independently revertible, and it is the one that carries the import churn;
  • a guard test that fails if a des2wf run can write PostgreSQL, since that boundary is the system's main invariant.