0.3.20 — production rollout and security fixes
This release deploys the platform changes in the 19 official-repository commits from 957f5d4c through 724a82fb, plus the build and private-render binding compatibility fixes found during release verification. Version 0.3.19 documented committed work and explicitly did not deploy application Workers; 0.3.20 records the production rollout.
Release verification fixes are split into four functional commits: d25c11fb, 8f6e39cf, c80b4788, 3ff9277f.
Product changes
- Next.js, TanStack, SvelteKit, Astro and Nuxt share the same backend for guest login, account conversion, protected workspaces, profiles, credits, orders, subscriptions, API keys and support. They include AI workspace and Image Agent entry points, with session-protected BFF routes.
- Public pages include searchable/category-filtered blogs, readable articles, locale/theme controls and clearer pricing. Login preserves the destination and selected pricing plan, without automatically starting checkout.
- Nuxt includes the Video Agent production workspace: project drafts, storyboards, scripts, reference assets, timelines, captions, voice revisions, render/export, delivery state and recovery.
- Updated the official website, Admin, core Admin, landing sites and ZSaaS build artifacts. The repository also includes the consumer browser-extension template and contributor/deployment documentation; browser-extension distribution is separate from this Cloudflare rollout.
Security and business behavior
-
Provider1 task reads and actions enforce the authenticated tenant and owner. Core Store lists, details and downloads use the authenticated app scope; explicitly public * items remain supported. A caller-supplied app_key cannot select another tenant’s items.
-
Core Admin authentication and AI proxy routes enforce server-side authorization and route restrictions.
-
Guest risk checks account for shared IP budgets and credit limits. Admin magic links use trusted configuration, not the request’s x-admin-public-origin header. Set the trusted Admin origin before using email sign-in.
-
Paid decision/prompt-optimization requests reserve credits before model calls. Failed, uncertain and retried operations preserve their ledger identity.
-
Subscription refunds and chargebacks retain credit-lot identities and durable recovery state. Stripe cumulative refund tracking prevents repeated partial-refund credit revocation. Store and GitHub-access compensation is persisted for retry instead of relying only on logs.
-
AI and Provider media downloads go through the private Node12 egress binding with an operator-owned HTTPS origin allowlist, redirect checks and response validation. Add required provider media origins deliberately; missing origins fail closed.
-
The private renderer accepts trusted Service Binding calls without copying the public HTTP key. Public requests still require a configured ZSHIP_KEY; job callback tokens remain required. Node10 render submission/recovery no longer requires or forwards the public HTTP key.
-
Updated frontend toolchains and fixed release build compatibility: Astro prerendering resolves cookie 2.x explicitly; the website imports the Tailwind CSS entry explicitly and uses PostCSS plugin options. SvelteKit bundles its runtime cookie, serialization and Markdown dependencies to avoid incompatible hoisted versions. OpenNext Cloudflare is updated to 1.20.12 for Next.js 16.4.3, including the preview-props.json runtime compatibility fix.
-
Astro automatic guest sessions now use a random, app-scoped HttpOnly browser cookie instead of an IP/user-agent-derived fingerprint, so visitors sharing a network do not share a guest identity.
Database migration checklist
Apply these migration files in numeric order within each service before deploying its new code. This production account already had Node1 0046_admin_magic_link_rate_limit.sql; older installations must apply it before 0047.
node1-auth-service: 0047_credit_read_indexes.sql.
node10-ai-service: 0027_video_production_pipeline.sql, 0028_video_scene_jobs.sql, 0029_video_production_recovery.sql, 0030_video_render_attempts.sql, 0031_video_selective_reuse.sql, 0032_video_reference_assets.sql, 0033_video_production_reconciliation.sql, 0034_video_planning_dispatch.sql, 0035_video_production_delivery.sql, 0036_video_production_verification.sql, 0037_video_production_voice_revisions.sql.
node3-pay-service: 0017_subscription_credit_source.sql, 0018_stripe_refund_state.sql.
zship-core-service: 0011_credit_compensation.sql.
zship-provider1-service: 0040_provider_media_capabilities.sql, 0041_seed_video_production_models.sql, 0042_video_production_reference_input.sql, 0043_correct_video_provider_contracts.sql.
The Node10 files rebuild only the new video-production tables when needed and preserve the legacy video workflow. Provider1 seeds and contract corrections target platform defaults while retaining tenant settings and existing credentials. Back up database state and check applied migration names before running wrangler d1 migrations apply <database> --remote, which applies every pending file in the configured directory.
Bindings, secrets and rollout order
- Apply and verify the D1 migrations above. Preserve existing account-specific D1, KV, R2, queue, secret and service bindings.
- Deploy
zship-node12-media-egress with MEDIA_EGRESS_ALLOWED_ORIGINS set to the approved provider and owned media origins; keep workers_dev: false, preview_urls: false and no public routes. Bind MEDIA_EGRESS on Node10 and Provider1 to this Worker.
- Deploy private
zship-video-render with RENDER_JOB → RenderJob and its v1 SQLite Durable Object migration. Keep it without public routes. Bind Node10 VIDEO_RENDER_SERVICE to it. No new shared public key or secret rotation is required for this binding-only path.
- Deploy Node1 before Node3 and other credit callers. Configure Node1
ADMIN_PUBLIC_ORIGIN (this account uses https://admin.zship.ai); preserve ADMIN_SECRET, JWT_SECRET and any existing ZSHIP_KEY secret bindings.
- Deploy Node10 before Provider1 and support callers. Preserve
IMAGE_AGENT_WORKFLOW, VIDEO_AGENT_WORKFLOW, private media R2/queues and IMAGE_AGENT_CREDENTIAL_KEY / IMAGE_AGENT_MEDIA_SIGNING_KEY. Add VIDEO_PRODUCTION_WORKFLOW → zship-video-production / VideoProductionWorkflow alongside VIDEO_RENDER_SERVICE and MEDIA_EGRESS.
- Deploy the affected payment, enterprise, Core, CDN, site, prompt, email, notification, blog, check-in and Cloudflare Admin services with their existing dependencies. Preserve the production notification queues, Node2
ERROR_REPORT_LIMITER and Node7 WAITLIST_JOIN_LIMITER. Core’s compensation retry cron is */15 * * * *; preserve other declared cron schedules.
- Deploy Admin, core Admin, the website and the five frontend templates after backend checks pass. Preserve frontend service bindings, the Nuxt content D1 database and Astro’s
SESSION KV namespace.
Video Stream clipping additionally requires the operator’s VIDEO_STREAM_ENABLED, VIDEO_STREAM_ACCOUNT_ID, VIDEO_STREAM_API_TOKEN, VIDEO_STREAM_CUSTOMER_CODE and optional VIDEO_STREAM_TOKEN_TTL_SECONDS. Deploying the workspace does not configure a paid media provider, Stream account or model automatically. Browser export and Stream clipping are separate delivery modes; no server-side ffmpeg container was provisioned in this rollout. Production readiness checks confirm Stream clipping remains unconfigured on this account; this release does not enable that delivery mode.
Verification scope
Release checks cover backend types/tests, production builds, migrations, deployed bindings, service health and bounded authentication/media rejection checks. They do not create paid model generations, purchases, refund transactions, emails or support messages. Provider credentials, model availability and actual paid generation require the operator’s configured services and a separate live transaction test.
The bounded Astro guest check reached the test client’s daily guest credit allowance and correctly returned 429; the limit was not raised. Guest-browser isolation is covered by regression tests.