AisleStage handles uploaded product images and commercial briefs as private workspace data. Do not include real customer data, credentials, deployment identifiers, private object URLs, or provider responses in issues, tests, screenshots, commits, or pull requests.
- The public product site and private
/appworkspace are separate routes. - Production authentication uses Cloudflare Access at the edge; the Worker independently validates the signed JWT issuer, audience, expiry, subject, and email before checking D1 membership.
- Access subjects are stored only as one-way hashes. Password login and registration are disabled in Access mode.
- Initial D1 lookups by Access subject hash and verified email are bounded availability checks. An unreadable lookup returns
503 unavailablewithout exposing database details or misclassifying a temporary storage failure as a membership denial. - A reported first-time Access-subject update failure is accepted only when an exact post-read matches the same user ID, normalized email, Access display name, subject hash, Access auth mode, and active status. A missing or unreadable binding returns the bounded
unavailablefailure and leaves the pre-onboarded account retryable. - When the explicitly enabled Access auto-provision batch reports failure, the Worker proceeds only if an exact post-read finds the active Access user by subject hash and normalized email. A missing or unreadable result is classified as bounded
503 unavailable, not as a membership denial; a committed transaction can recover, while a definitely uncommitted transaction leaves no account rows. - Protected APIs require a verified Access identity, an active account, and a matching active D1 workspace membership.
- The Worker applies the private workspace shell's CSP,
X-Frame-Options: DENY, restrictive Permissions Policy,Referrer-Policy: no-referrer, no-sniff, same-origin resource policy, and no-store caching after authorization, without relying on the Static Assets response to supply those controls. - After authorization succeeds, an unreadable
/api/workspaceslist returns a bilingual no-store503 unavailablewithout exposing D1 details or changing the established session state. - The private generation list rechecks the active user-workspace scope before reading up to 20 rows. An unreadable scope or list query returns bilingual no-store
503 unavailablerather than a partial or empty result, while a requested cross-workspace identifier remains404. The browser reads no non-success body and accepts only an exact200 application/jsonresponse containing the one-field generation-list envelope before applying the bounded generation normalizer. - The browser replaces its current generation snapshot only after a successful response supplies at most 20 unique, complete generation envelopes with valid workflow, ratio, state, review/provenance revision, and exact same-origin preview/download paths bound to each generation ID. List and Campaign Pack success responses share this normalizer; network failures, non-success responses, external URLs, and malformed payloads retain the authenticated session and existing outputs while presenting a bilingual notice. Only an explicit empty array represents no outputs.
- Browser-local PNG export is offered only for a completed, approved
deterministic-svg-v1result whose revision, provenance, fixed ratio, image path, and download path remain canonical. It fetches the same authorized download route with same-origin credentials, a 30-second deadline, an 18 MiB decoded-byte limit, a 1,024-chunk limit, fatal UTF-8 decoding, and exact SVG MIME and attachment metadata. Before Canvas receives the body, a narrow tag, attribute, entity, ID, fragment-reference, embedded-image, element-count, and fixed-dimension allowlist rejects scripts, event handlers, external resources, arbitrary CSS URLs, doctypes, entities, and unsupported SVG structures. The resulting PNG must have the PNG signature, be non-empty, and remain within 16 MiB. Both temporary object URLs are revoked, conversion failures expose only a fixed bilingual message, and neither the derivative nor conversion state is uploaded, written to D1/R2, or allowed to change the approved SVG. - JSON and multipart write routes require an exact, case-insensitive base media type before bounded body parsing. Standard parameters remain supported, while substring lookalikes such as JSONP-style or prefixed media types cancel the unread stream and fail with
415before password verification or endpoint mutation; protected routes still complete their required session and membership checks first. - Session and invitation tokens are stored as hashes; authentication abuse records use one-way email and IP keys.
- Each authentication-abuse event has a server-generated ID. A reported insert failure proceeds only when that ID resolves to the exact email hash, IP hash, and event type; the same primary key and exact fields permit one bounded write retry when the first event remains missing or its first reconciliation read is unavailable. A committed event is not duplicated, conflicting state is never overwritten, and a still-unconfirmed event or unreadable rate-limit count returns a bilingual
503. Successful credentials receive no session in that failure state, and unrelated application errors are not hidden by this mapping. - A reported session-insert failure is reconciled only by the newly generated token hash, expected user, and exact expiry. A matching committed row may issue the original hardened cookie only after active membership is rechecked. Missing or conflicting state returns a bilingual failure without exposing the token or hash; unreadable reconciliation or authorization reload also returns no cookie and best-effort removes the unique undelivered session row, without deleting a readable conflicting row.
- Password-session authorization treats unreadable session, active-user, or workspace-membership state as a bilingual no-store
503 unavailable. It retains the browser cookie for safe retry and does not misclassify a temporary D1 failure as a signed-out or expired session. - The browser accepts an authenticated bootstrap only from an exact
200 application/jsonresponse whose success envelope contains an active bounded user, an active bounded workspace, a supported role, and non-negative safe-integer allowances. It applies the same transport requirement to the exact restricted health envelope and its registration/generation cross-field invariants. Non-success session responses are not parsed; only the boundedx-aislestage-access-failureheader may select a fixed Access failure state. Malformed or contradictory success payloads fail closed to fixed bilingual unavailable states rather than changing client authorization or feature controls. - Private browser hydration enforces decoded stream limits before JSON parsing: 4 KiB for platform status, 16 KiB for session state, 128 KiB for the generation list, and 256 KiB for Agent state.
Content-Lengthis only an early rejection signal; actual streamed bytes remain authoritative, oversized bodies are cancelled, and no partial snapshot is applied. - Concurrent initial hydration within one mounted workspace shares one in-flight session/health and, only after an authenticated session, generation/Agent snapshot. The promise is cleared on success or failure rather than caching private data across loads. Effect teardown, logout, and newer authentication advance an epoch so an older private snapshot cannot repopulate client state.
- Session, platform-status, generation-list, and Agent-state GET requests use a 15-second AbortController deadline. Expiry maps to the same bounded unavailable state, releases the loading UI, and does not replace an existing workspace snapshot. Mutation commit uncertainty remains governed by each endpoint's reconciliation and retry contract rather than this GET-only deadline.
- Private mutation acknowledgements use the same reader before schema validation: 1 KiB for logout, 4 KiB for product upload, 16 KiB for password authentication and output review, 64 KiB for Campaign Pack creation, and 256 KiB for Agent actions. Oversized success bodies cannot confirm a login, logout, upload, plan, pack, or review decision.
- Versioned Campaign Brief JSON import and export are browser-only and make no network request. Import is limited to 64 KiB exact local bytes with a 10-second deadline, fatal UTF-8 decode, exact known fields, supported intent, safe hex colors, and the same text/list limits used by planning; malformed or expanded files do not change state. Export omits asset, workspace, user, provider, and deployment identities, uses a generic filename, and revokes its temporary Object URL. The downloaded file still contains the user's commercial copy and should be stored as private business material.
- The password-auth client sends only endpoint-required fields: login excludes retained registration names and invitation codes, while registration includes an invitation code only in invite mode. Fields are normalized and bounded before a 6 KiB client body cap. Login requires exact
200 application/jsonand registration requires exact201 application/jsonbefore both reuse the active-session normalizer; non-success payload text is never reflected directly into the form. - Password login and registration each make one 30-second POST attempt, including complete response consumption, and never resend a password, invitation code, or account-creation mutation automatically. Transport failure, response-stream interruption, expiry, HTTP
408, or5xxtriggers only one bounded/api/sessionGET. Login reconciliation requires the exact normalized email; registration additionally requires the exact submitted name, workspace name, and owner role. Client validation, authorization, conflicts, rate limits, oversized or malformed success bodies, wrong status/media type, and mismatched identities are not reconciled. A synchronous form lock disables mode tabs and every credential field until the attempt and optional reconciliation settle. - Session
last_seen_atis non-authoritative, best-effort telemetry that never extends the fixed expiry. Its update runs only after the active user, unexpired session, and active workspace membership are verified; update failure cannot override that completed authorization decision. - A reported logout deletion failure is successful only when the same token-hash row is confirmed absent. If the row still exists or reconciliation is unreadable, the route returns a generic failure and retains the browser cookie as a retry anchor instead of falsely claiming that the server session was revoked.
- In password mode, the browser clears private workspace state only after an exact
200 application/jsonresponse containing only{ "ok": true }. Each no-body logout attempt, including complete response consumption, has a 15-second deadline; transport failure, response-stream interruption, expiry, HTTP408, or5xxreceives at most one automatic retry while the same cookie remains available. Validation, authorization, and non-canonical success responses are not replayed. Two failed attempts retain the visible signed-in state and release the logout control for an explicit retry without reflecting server details. Access mode navigates directly to the fixed same-origin/cdn-cgi/access/logoutpath and does not accept a response-controlled redirect. - A reported password-registration batch failure is reconciled only by the server-generated user and workspace IDs plus exact password-account fields, active workspace, owner membership, initial allowance, and invitation linkage. A matching committed batch records one success and may create the session; an unrelated account with the same email cannot satisfy reconciliation, and conflicting or unreadable state fails closed without returning identifiers.
- The invite CLI accepts recipient data only from a protected environment, uses fixed generic D1 configuration, and rejects unknown, positional, duplicate, missing-value, invalid, or protected command arguments before generating invite material or invoking Wrangler.
- The owner onboarding CLI accepts identity data only from protected environment input and requires exactly one explicit
--localor--remotetarget. Unknown, positional, duplicate, valued, missing-target, conflicting-target, or mixed self-test options fail before identity access or Wrangler execution; dry-run never reads or changes D1. - Scheduled minimization removes expired sessions, authentication-attempt records after 7 days, expired pending/revoked invitation hashes, and used invitation linkage after 30 days.
- Product images are limited to PNG, JPEG, or static WebP, 4 MB, 8192 px per side, and 32 megapixels, then stored in private R2 paths generated by the server. PNG chunks, JPEG structural markers, and WebP chunks have explicit traversal-count bounds; PNG critical chunks, CRCs, trailer, indexed-color palette capacity, and the color-type, length, palette, uniqueness, and ordering rules for
tRNStransparency are checked, while JPEG frames and WebP RIFF, padding, and static VP8/VP8L headers provide dimensions without decoding the private image. PNG chunks marked private and unrecognized WebP chunks are rejected before storage so application-specific payloads cannot be retained silently. Upload supplies a SHA-256 checksum to R2 and stores the verified canonical digest in D1. - Before multipart upload, the browser replaces the local filename with a MIME-derived generic name. It accepts only an exact
201 application/jsonsuccess envelope whose UUID, canonical name, MIME, byte count, and same-origin preview path match the submitted file; malformed or unrelated responses fail closed, and server error details are not reflected into the workspace. While that upload is pending, every file-input, replace, and delete control for the product image is disabled so a competing browser action cannot supersede the in-flight private asset mutation. - Every product-image upload carries a client-generated UUID v4 idempotency key that the Worker validates before reading the multipart body and uses as the returned asset identity. A replay in the same workspace succeeds only when object identity, MIME, byte count, and SHA-256 match; the browser also requires the response asset ID to equal its request key. The same key with different content returns a fixed conflict, and the key cannot replay an asset across workspaces. Browser upload attempts, including complete success-body consumption, have a 45-second deadline and at most one automatic retry with the same key for transport failure, response-stream interruption, deadline expiry, HTTP
408, or5xx; validation, authorization, conflict, and malformed-success responses are never automatically replayed. - Private product-image reads preserve workspace-scoped
404responses for absent or unauthorized assets. Successful image bodies useprivate, no-storeandCross-Origin-Resource-Policy: same-origin, so a browser cannot reuse them after a logout or account change or embed them as a cross-origin subresource. If the scoped D1 metadata lookup or subsequent R2 object read is unavailable, the route instead returns a bilingual no-store503 unavailablewithout exposing storage errors, object keys, or workspace identifiers. - After a verified R2 upload, a reported D1 insert failure is reconciled by the request-bound asset ID and exact canonical fields. Candidate R2 objects are separated by content digest, so concurrent different payloads using one key cannot overwrite each other; the losing request removes only its unreferenced candidate. A matching committed row returns the original success response, while a confirmed missing row triggers single-object cleanup. If D1 reconciliation is unavailable, or a candidate path is already referenced, the route fails closed without blindly deleting the retry anchor.
- Images containing EXIF, XMP, or text metadata are rejected, and original filenames are not retained.
- Campaign Agent state is workspace-scoped and can be changed only through server methods.
- Agent-stub acquisition and state RPC failures are contained by the same route boundary, which logs only a fixed action label and returns a bilingual no-store
503without Durable Object details. The browser requires exact200 application/jsonwith one outerstatefield before applying the complete, bounded Agent-state envelope; unavailable, expanded, or malformed responses retain the current plan rather than replacing it with a fabricated idle state. - Campaign Agent GET, plan, and approve responses share the bounded state normalizer and require unique check, plan, and message identities. Plan and approve actions require exact
200 application/json; plan success is accepted only for the canonical submitted brief and a planning stage, while approval success must confirm the requested revision, an approved timestamp, and a boolean replay marker. Action requests have a 40 KiB client cap, and arbitrary server error text is not reflected into the workspace. - Browser planning has one 40-second attempt, including complete response consumption. Because planning advances revision and is not replay-safe, transport failure, response-stream interruption, expiry, HTTP
408, or5xxnever triggers a second plan mutation; one bounded state GET reconciles success only when the canonical submitted brief matches and the revision advanced beyond the captured baseline. Approval has a 15-second deadline per attempt and may retry once with the same revision after the same temporary failures because the server returns an idempotent replay for an already approved revision. Validation, authorization, conflict, and non-canonical success responses are neither retried nor reconciled. The submitted brief, source-image controls, planning, approval, and Campaign Pack creation stay locked until the Agent action settles. - Campaign approval accepts a bounded JSON object containing exactly one positive integer revision. Strings, booleans, nulls, extra fields, and numeric coercion fail before asset checks or Agent mutation; concurrent or repeated approval of the same revision is idempotent and cannot append duplicate approval messages.
- Campaign planning requires an exact outer object containing one non-null brief object; missing, null, array, primitive, extra-field, or malformed envelopes fail before Agent mutation and cannot replace an approved revision with an empty brief. Supplied brief fields are then checked for value types, supported locale, list counts, and lengths before sanitization, private asset lookup, or provider work. Input that would be silently truncated, dropped, or remapped fails with a bilingual
422that does not echo the submitted value and cannot replace the current revision. - Campaign Brief, brand, and product objects reject unknown fields before sanitization. Campaign Pack and single-generation routes apply the same nested schema, and the single-generation route also requires the exact GenerationInput key set, so ignored client controls cannot enter persisted input JSON.
- Complete brand data requires one to eight exact six-digit
#RRGGBBcolors. Browser files and controls, Agent state and actions, saved brand snapshots, Campaign Pack requests, Worker generation inputs, and the deterministic compositor share this validation. Brand previews and SVG composition use a fixed safe fallback for any non-canonical runtime value instead of reflecting arbitrary CSS or URL syntax. - Configured forbidden terms are split on explicit line or punctuation delimiters and compared against normalized Chinese and English commercial copy before approval and composition. A match returns only a fixed bilingual correction message; the configured term is not reflected in the error. Target-channel entries remain brief metadata and do not trigger external publication.
- Product-asset and completed-output deletion require a successful workspace-scoped D1 metadata preflight before any R2, Agent, or D1 mutation. An unreadable preflight returns a fixed bilingual no-store
503, logs no private identifiers, and preserves the D1 row, private object, and Agent revision. - The browser deletion client accepts only one bounded safe identifier and one same-origin route per action, sends no body, and treats only
204or an authoritative workspace-scoped404as absent. Its 15-second AbortController deadline releases a stalled action without removing local state; the same explicit delete remains safe to retry because both confirmed deletion and confirmed absence are successful outcomes. Other success codes, processing conflicts, authorization changes, transport failures, and storage failures retain local state and use fixed bilingual messages without parsing server error details. - Product-asset deletion completes the private R2 delete before conditionally resetting Agent state inside the workspace Durable Object and deleting the D1 record. If the R2 delete call rejects, the Worker does not mutate the D1 record or current revision, retaining a retry anchor; a completed deletion resets state only when the current brief references that exact asset. If the final D1 delete response is ambiguous, a scoped absence check returns idempotent success only for a confirmed commit; a retained or unreadable row fails closed for retry. Deleting an unrelated private source keeps the existing revision, and the browser reloads authoritative Agent state after deletion instead of assuming every plan was reset.
- Completed-output deletion keeps its workspace-scoped D1 row as the retry anchor until the private R2 delete succeeds. If the final D1 delete response is ambiguous, a workspace-scoped absence check returns idempotent success only when the row is confirmed gone; a retained or unreadable row fails closed so the explicit delete can be retried.
- Generation requires the current approved revision and an exact match of the approved brief, source asset, workflow, and ratio.
- Campaign Pack creation is atomic and idempotent; Queue processing and output allowance accounting remain idempotent under duplicate delivery.
- A Queue claim whose D1 response is unconfirmed never starts provider or R2 work and never releases the reservation during the bounded retry window. A confirmed queued or same-attempt processing row, as well as temporarily unreadable reconciliation state, is deferred to the next Queue attempt; terminal, missing, or newer-attempt state is not overwritten by the stale delivery. Once confirmed, the processing-attempt number fences canonical reads, approval and asset rechecks, completion, retry reset, and terminal release. A stale attempt cannot mutate the newer owner; if ownership changes after its R2 put, the unreferenced object is removed.
- A reported Campaign Pack batch failure is reconciled against the server-generated pack ID, three canonical queued rows, blank output state, and one exact reservation per output before normal Queue dispatch. If reconciliation is temporarily unreadable, the bounded local Queue batch is still dispatched so a possibly committed pack cannot remain stranded, while the client receives a generic failure; messages without matching D1 rows cannot claim work. Conflicting state fails closed without blind allowance compensation.
- If Campaign Pack commit and Queue dispatch succeed but the final generation snapshot is unreadable, the route returns a fixed bilingual no-store
503without releasing reservations, duplicating Queue delivery, or guessing output data. Retrying the retained idempotency key returns the original pack and generation identities through canonical replay. - The single-generation compatibility route reconciles reported reservation-batch and generation-insert failures by the server-generated generation ID. It proceeds only for one exact reservation and one canonical queued row, releases only a confirmed rowless reservation, and avoids destructive compensation when state is unknown or conflicting.
- Campaign Pack creation accepts an exact outer JSON envelope and exact two-field output entries. Unknown fields or malformed structures fail before approval reads, allowance reservation, D1 writes, or Queue work.
- The browser Campaign Pack client rebuilds the canonical eight-field request from one validated approved brief, one source asset, and exactly three unique supported workflow/ratio pairs under a 32 KiB UTF-8 cap. It accepts only the exact
202creation or200idempotent-replay envelope, then binds UUIDs, pack identity, generation count, approved revision, and the complete requested output set through the shared generation normalizer; arbitrary server error text and expanded response fields never enter workspace state. - Each Campaign Pack browser attempt, including complete response consumption, has a 30-second deadline. Transport failure, response-stream interruption, expiry, HTTP
408, or5xxreceives at most one automatic retry with the same canonical body and idempotency key; validation, authorization, allowance or approval conflict, and non-canonical success responses are not replayed. While the request and bounded polling are active, the browser locks the approved brief, source-image mutations, planning, and duplicate creation. A valid replay refreshes the authoritative session before displaying allowance instead of blindly reserving three outputs again; terminal replay results are applied without waiting for another poll. - After a pack is confirmed queued, browser polling is bound to its exact three generation identities for 16 fixed intervals. A temporary bounded list-read failure does not turn a committed pack into a creation failure or erase the last trusted snapshot. Any successful read resets the failure count; three consecutive failures stop polling, release the UI lock, refresh allowance when possible, and show a fixed bilingual queued-but-unavailable status. Only all three expected identities in terminal states complete the poll.
- Opening or explicitly refreshing Campaign Packs or the private asset library issues at most one serialized bounded generation-list GET. Review and deletion mutations disable the refresh control, stale hydration responses cannot replace a newer refresh, and logout invalidates any in-flight result. An unavailable or malformed refresh preserves the last trusted rows and displays the fixed bilingual list error inside the collection view; the public demo makes no private API request.
- Campaign Pack and single-output creation re-read active workspace scope and product-asset ownership before allowance, generation, or Queue mutation. An unreadable D1 preflight returns a fixed bilingual no-store
503 unavailable, logs no private identifiers, and creates no pack, generation, ledger, reservation, or Queue message instead of misclassifying storage failure as a missing workspace or asset. - A Campaign Pack idempotency key is bound to the complete canonical generation identities stored with the existing pack. Reuse with a different revision, brief, asset, workflow, ratio, or output count fails with
409and cannot return an unrelated pack or alter allowance. - Completed outputs remain private drafts. Only an owner or admin can make the immutable review decision, and only approved output receives a separate download route.
- Before any review mutation, an unreadable workspace-scoped D1 generation row or approval-time R2 metadata check returns a bilingual no-store
503. The output remains a draft, no decision timestamp is written, and fixed logs contain no generation, workspace, or object identifier. - A reported review-update failure is reconciled by the workspace-scoped generation ID, completed state, target decision, expected approved revision, and non-empty review timestamp. A matching immutable decision returns as an idempotent replay; a confirmed draft stays non-downloadable with a retryable failure, and an opposite decision remains a conflict.
- If the conditional review update succeeds but its authoritative generation reload is unreadable, the route returns the same retryable
503without guessing a response. Repeating the same decision observes the committed immutable state and returns it as an idempotent replay. - The browser serializes review actions and keeps the selected draft visible until an exact response is verified. Each attempt, including complete response consumption, has a 15-second deadline; transport failure, response-stream interruption, expiry, HTTP
408, or5xxreceives at most one automatic retry with the same generation, decision, and approved revision. Authorization, validation, conflict, and non-canonical success responses are not replayed. Two failed attempts release the review controls without changing the draft or exposing server details. - The browser revalidates its current completed draft before review, submits only the decision and expected approved revision, and accepts only an exact
200 application/jsonreviewed-generation envelope. Generation identity, Campaign Pack, workflow, ratio, content metadata, creation time, image route, and provenance must remain unchanged while the requested review state and controlled download route are confirmed; arbitrary server error details are not reflected into the workspace. - Generated previews and approved downloads are served only through authorized, workspace-scoped Worker routes with
private, no-store,Cross-Origin-Resource-Policy: same-origin, and restrictive response headers, preventing cross-origin subresource embedding and a browser cache from carrying a private SVG across sessions. - Preview and approved-download delivery distinguish absent or unauthorized output (
404) and integrity failure (409) from temporary storage failure. An unreadable workspace-scoped D1 generation row or R2 output object returns bilingual no-store503 unavailable, logs no private identifiers, and returns no SVG body. - Queue output upload supplies a SHA-256 checksum to R2 and stores the same canonical digest in D1. Approval and delivery require that digest, the SVG type, and private R2 HTTP/provenance metadata to match; a mismatch blocks approval and returns no object body.
- A reported Queue completion-batch failure is reconciled against the exact completed row, canonical R2 metadata, draft review state, and unique settlement ledger. A committed completion is acknowledged without deleting its object; a confirmed uncommitted attempt removes its object before bounded retry. Unknown or conflicting state never triggers a blind deletion of a potentially referenced private output.
- Agent planning verifies source workspace ownership and the D1/R2 checksum, size, MIME, asset kind, and workspace metadata before any Durable Object mutation or optional provider work. Product preview, Agent approval, and Queue source reads repeat the canonical check; missing, cross-workspace, or mismatched input returns no image body and does not replace the current Agent revision.
- Deterministic mode does not contact an external model provider. Assisted modes require an explicit server-side gate and never send the private asset identifier to the provider. The image adapter rejects unsupported ratios, non-empty reference URL lists, and empty or over-4,000-character prompts before network egress.
- Successful provider responses are read through actual-byte and fragmentation limits rather than trusting
Content-Length; JSON MIME, UTF-8, exact local fields, text lengths, and base64 size are revalidated before use. Decoded PNG responses must also pass the shared signature, chunk-order, CRC,tRNSsemantics, non-empty IDAT, canonical IEND, 8192 px/32 MP dimension, and EXIF/text-metadata rejection checks. The response IHDR must exactly match the server-selected dimensions sent for its requested ratio before decompression. IDAT zlib is streamed through an IHDR-derived scanline/filter validator with a 128 MiB decoded limit before the image can enter a reviewable SVG. - Provider requests, complete response-body reads, and PNG decompression share a 30-second deadline. A timeout aborts the work, follows the bounded Queue retry policy, and releases reserved allowance exactly once only after terminal failure.
- Browser assets are same-origin and do not use third-party analytics or font requests.
- User-facing errors and persisted observability events exclude commercial brief contents, provider payloads, deployment mappings, database diagnostics, queue details, and private object keys.
- Workers invocation logs are disabled for protected path privacy; custom error logs use bounded event names without user, workspace, asset, brief, prompt, response, or object-key values.
- AI Gateway or another proxy may record metadata only after approval. Raw request and response payload collection remains disabled for private commercial work.
- Payment is disabled in this repository. A future payment boundary must use authenticated server-to-server or Service Binding calls, verified events, replay protection, and provider-neutral domain types; the browser never receives privileged credentials.
Tracked Wrangler configuration contains placeholders and generic binding names only. Keep account IDs, database IDs, resource names, deployment URLs, secrets, private operational data, and non-public business material in protected deployment configuration.
Local and automated tests must use synthetic records and isolated bindings. Do not connect tests to production resources or paid provider calls.
Before a public commit, push, pull request, release, or deployment, run npm run release:check. Confidential custom terms are supplied through a protected local input and are never embedded in the repository or printed by the scanner. GitHub secret scanning is defence in depth rather than release proof.
GitHub CI uses only the public placeholder configuration and holds no Cloudflare credentials or resource mappings. Production deployment uses either an ignored, user-restricted local Wrangler configuration or the aislestage Worker's Cloudflare Workers Builds connection. Workers Builds keeps its dedicated token and resource mappings in protected Cloudflare settings, writes only an ignored permission-restricted generated configuration, and deploys production only from main. Neither deployment configuration may be uploaded as an artifact or copied into logs, pull requests, issues, or public documentation.
Report a vulnerability privately through the repository Security tab. Include the affected route or file and a minimal synthetic reproduction. Redact tokens, cookies, emails, private object keys, infrastructure identifiers, and real user data.