Skip to content

Releases: shipwords-dev/shipwords

Release list

v0.1.0

Choose a tag to compare

@GargantuaX GargantuaX released this 31 Oct 17:23

The first tagged release of shipwords. Pin your fork to a tag from now on, and read the upgrade notes below before pulling a newer one.

tinydeskai.io runs this version in production; its source is in sites/tinydeskai-example.

Upgrading a site forked before this release

Do these in order. Commands with pnpm db:* run in the site directory; the rest run from the repo root. Finish with pnpm --filter "./sites/<site>" check.

  1. Split the models file. site.models.ts now uses definePublicModels and holds only what pages show (name, credits, guest, inputs, effect slots). Everything else (upstream model, maxCost, timeout, prompts, effect presets) moves to a new src/models.server.ts using serverModels, keyed by the same ids. Then point the two server entries at it: in src/core.server.ts and src/server.ts, change import models from '../site.models' to import models from './models.server'. Pages keep importing site.models.ts. Extra fields in site.models.ts are rejected (top-level ones at typecheck, nested ones when the file loads), and check-site requires src/models.server.ts. See the template and the example site.
  2. Add signup.bonusSiteDaily to site.config.ts: how many sign-up bonuses the whole site grants per day (0 when the site gives none). It is required.
  3. Check BETTER_AUTH_SECRET. It must now be at least 32 random characters (openssl rand -base64 32), locally and in production; auth and every request that needs it fail otherwise.
  4. Generate and apply a migration: pnpm db:generate, then pnpm db:migrate:local, and pnpm db:migrate:remote when you deploy. It adds the nullable column jobs.upstream_cost_usd.
  5. Update package.json: add "devPort" (each site gets a fixed dev port, 10 apart; pnpm new-site assigns the next free one), then run pnpm setup:worktree so APP_URL in your .dev.vars follows the new port, and add http://localhost:<port> to your Google OAuth origins. Make deploy / deploy:preview run node ../../tools/check-site.mjs . after the build, as the template does; it now scans the client bundle for strings from *.server.ts files and for .dev.vars values.
  6. Effect models with prep: recheck maxCost. A slow prep now gets a second, hedged copy, so the model's maxCost must cover the sum of segment caps, plus every repair round, plus twice the prep cap per prepped slot. A config that only covered one prep each throws at load.
  7. If the UI cancels jobs, show the cancel button only while the job is queued (see the template's JobCard); after that the API refuses with 409 job_started.
  8. If you use the compose container, redeploy. The old image ignored SIGTERM, so instances kept running and billing memory for hours after each job. The fixed image is built from packages/jobs/compose on deploy.

If you extended the engine

  • emailOnSuccess is now emailOnFinish; its site option needs defaultLocale, and it also emails failed jobs.
  • A custom payment adapter's PaymentFact needs metadataTrusted. Set it to true only when the metadata cannot be set by the buyer (Stripe); otherwise payments below the list price are refused.
  • A custom Composer (or test double) needs likeness, extract and patch.
  • EffectCheck.retries is gone: a missed swap no longer reruns the segment. Use segment.repair instead.
  • MockAdapter's third argument is now the site URL, not the fallback file URL.
  • UI that read job.error.message must switch to job.error.code.

Behavior changes

  • No refund on a path the customer can repeat after the upstream has charged. A cancel only works while the job is queued; once the upstream has it, POST /api/jobs/:id/cancel answers 409 job_started and the job keeps going. useGeneration's cancel absorbs that. Cancelled guest jobs no longer return guest quota. See architecture §6.
  • job.error carries only a code, not the stored message (which could hold upstream replies and face-check scores). Show your own copy per code.
  • Uploads under 160 px on the short side are rejected with 422 image_too_small; files whose size header can't be read get 415 invalid_image.
  • Sign-up attribution goes to the first visit that has a source (UTM or outside referrer), not simply the first visit. Your own pages and payment checkouts no longer count as referrers.
  • Engine emails (sign-in codes, job finished or failed) follow defaultLocale: built-in copy for en, ja and ko, English otherwise. Failed jobs now get an email too.
  • jobs.upstream_cost_usd records what the upstream reported for the job's recorded tasks, best effort: a hedged prep copy is not counted, so treat it as a floor, not the exact cost.

New

  • Music jobs: a third job kind (style prompt plus optional lyrics in, songs out) through Yir's music endpoint. Stored MP3s have provider ID3 tags stripped.
  • Repair for missed face swaps (segment.repair): missed shots are re-rendered with a replace model, with optional crops for people at the frame edge and a likeness threshold for close-ups. With onMiss: 'deliver', a missed swap or a check problem after the upstream has charged delivers the best version so far instead of refunding; a render or compose that fails outright still refunds.
  • Faster photo prep: a prep that runs over a minute gets a hedged second copy, and all preps are polled together.
  • Phone photos: photos over 8 MB or in a format other than PNG/JPEG/WebP (HEIC included) are redrawn as JPEG in the browser before upload when the browser can decode them; otherwise the upload fails with a readable error. Use UPLOAD_ACCEPT and acceptsUpload from @shipwords/jobs/react for file pickers and drag and drop.
  • Money-path fixes: quota counts roll back when a later quota write fails; PayPal only grants credits when the payment covers the list price in the list currency.