Volter World

Twins / Upstash / 1.0.2

@volter/twin-upstash

Upstash

volter-aiVolter maintainedSelected defaultv1.0.2

Deterministic Upstash Redis over REST, rate-limit client calls, and QStash workflows; no live Upstash calls.

The example uses Upstash 1.0.2. Keep its dependency pins when following it.

Setup gives the current installation instructions for @volter/twin-upstash 1.0.2. Open the published README for credentials, seeds, supported operations and limits.

README shipped with @volter/twin-upstash 1.0.2

These instructions were published with this package. Their tool versions may differ from the current starter cohort. Use Setup to install this version.

A local Upstash: Redis over Upstash's REST API, the one the unmodified @upstash/redis and @upstash/ratelimit call (https://<endpoint>.upstash.io, this unit), the console where a database and QStash's credentials are made (console.upstash.com, the api/ lane, beside the Developer API's spec), and QStash with Workflow (https://qstash[-<region>].upstash.io, the qstash/ lane), over one vendor state.

Use with an existing app

Use Node 22.6 or newer.

For an app using the supported Redis REST or QStash workflows, install the exact release:

npm install --save-dev --save-exact @volter/world@3.0.147 @volter/twin-upstash@1.0.2
./node_modules/.bin/volter world init --name my-app --twins upstash --source upstash=@volter/twin-upstash

Run the local executable from this app’s folder; if it is missing, complete the installation here before continuing.

Review the detected vendor and generated bindings before booting. The World supplies throwaway credentials; seed stored data through the unchanged vendor SDK, then run your app's existing test command inside the World.

./node_modules/.bin/volter world up
./node_modules/.bin/volter world run -- npm test
./node_modules/.bin/volter world log
./node_modules/.bin/volter world down

Use your app's test command in place of npm test. Ordinary down retains state for the next up.

A Protocol 3 pack (publisher guide). The Redis unit's surface is Redis's command table (spec/commands), and its front (src/semantics/around.ts) reads Upstash's REST forms and runs the commands with the kernel's Redis core under Upstash's dialect (src/semantics/shared.ts). Each lane's surface is generated from its own spec, with handlers in <lane>/src/semantics/<family>.ts and state machines in <lane>/src/semantics/states.ts.

world-upstash serve [--port N] [--root DIR] [--read-only]

The World's Upstash

A person signs in to the console and creates a Redis database there (name, primary region, the free plan). The database's page shows UPSTASH_REDIS_REST_URL, UPSTASH_REDIS_REST_TOKEN and the Read Only token. On a first visit to QStash they pick a region; the page then shows QSTASH_URL, QSTASH_TOKEN and the two signing keys, and can reset the token and roll the keys. The Redis console has the vendor product navigation, a Create Database dialog and database Details/Connect sections. Redis Usage, CLI, Data Browser, Search, Monitor, Backups, ACL and paid/read-region controls remain unavailable; no usage metrics are fabricated. QStash uses the same product navigation and an Overview with masked Quickstart credentials, a token reset confirmation and signing-key rotation. QStash message, usage and cost charts and unserved navigation are unavailable; its read-only-token switch is not reproduced.

What it models

  • Redis over REST: a command in the path (/set/foo/bar, a POST body as its last argument) or the body (["SET", "foo", "bar"]), /pipeline and /multi-exec, {result} / {error}, Upstash-Encoding: base64, Upstash-Response-Format: resp2 (RESP2 bytes, but at /multi-exec), and a database's Standard and Read Only tokens (the Read Only one refuses writes, SCAN and KEYS).
  • Redis's semantics are the kernel's (@volter/world-core/redis), for the commands Dub sends and the life sends (src/semantics/shared.ts, SERVED): SET, GET, GETDEL, DEL, EXISTS, EXPIRE, PEXPIRE, INCR, INCRBY, RENAME; HSET, HSETNX, HGET, HGETALL, HMGET, HDEL, HINCRBY; LPUSH, RPUSH, LPOP, LRANGE; SADD, SREM, SMEMBERS, SISMEMBER, SMISMEMBER; ZINCRBY, ZRANGE; XADD, XRANGE, XREVRANGE, XDEL; SCAN; EVAL and EVALSHA running the script's Lua (@upstash/ratelimit's windows verbatim). Every other command is refused as Upstash refuses one it does not have, in a request or a script.
  • Lua script flags: no-writes prevents script mutations. allow-key-locking restricts commands to declared Redis hash tags, including dynamic keys sharing those tags; scripts in /multi-exec use the vendor's transaction exception. Script hashes include the header. Other flags, database-wide reads under key locking, and Search-index locking are not modeled; this does not simulate parallel scheduling.
  • QStash:
    • Publishing: publish with method, timeout, delay, not-before, retries, deduplication (ten minutes), flow control's keyed rate, period and parallelism (a key alone keeps its limits), durations as <number><unit> or compound (1d1h30m), retry-delay expressions, comma-separated labels, callbacks and failure callbacks, each configured by its own Upstash-Callback-* / Upstash-Failure-Callback-* options; batch; enqueue into a queue, and a queue's upsert; the token as a bearer header or qstash_token. A destination that is not a URL is a URL Group the account does not hold (404).
    • Messages: a message's read with configured body/header redaction; cancellation by message ids, filters, or all pending messages in the account. Redaction preserves the original payload for delivery.
    • Delivery: each message is delivered when due, signed (Upstash-Signature, HS256 with the current key), and retried on QStash's backoff, each attempt waiting at most its timeout (the account's Pay as you go plan's two hours, which an Upstash-Timeout only shortens). Once out of retries, or answered 489 with Upstash-NonRetryable-Error: true, it goes to the DLQ and its failure callback is called. A queue delivers in order, as many at a time as its parallelism; the attempts due at one instant are sent at once, and a call holds its key's slot until its answer arrives.
  • Workflow: a run is started by its first invocation, and each later call carries the run's steps so far. It ends when serve() ends it or when it is cancelled; when a step is out of retries it fails.

Doors

  • POST /_twin/users/{email} {password} (console.upstash.com): a person who can sign in.
  • POST /_twin/app-credentials {owner?} (console.upstash.com): a World application's database and QStash credentials, as the runtime issues them (the descriptor's credential door).
  • POST /_twin/destinations {url, status, headers?, body?, takes?, when?} (QStash): how an application the World does not run answers at a URL, and after how long on the World's clock.
  • GET /_twin/deliveries?to=<url>[&run=<id>][&message=<id>] (QStash): every request QStash made there, with its answer's status once it arrived, or what was missed (timeout, unreachable).

Who it is for

Dub, as it ships (journeys/demand.json): its Redis caches, locks, streams and imports, its rate limits, its QStash jobs, queues and Workflow runs, and the deliveries its routes verify. Rallly and Cal.com use Upstash Redis only when their variables are set. The life (journeys/customer-life.json) is one studio's quarter on one account: Kiln on Redis, Looplinks on QStash and Workflow.

Not yet

  • The Developer API (api.upstash.com/v2): no application calls it; the console makes what they use.
  • QStash's schedules, URL groups, the DLQ's API, waiting for events, flow control's management API; a message read only while it is delivered or retried, as QStash keeps it.
  • Every Redis command no demand or life sends (Upstash's table holds 248).
  • Upstash Vector (Dub's docs embeddings): another product with its own wire.

Set up this release

The example uses Upstash 1.0.2. Keep its dependency pins when following it.

For a complete example, follow Redis data and quotas. It includes the application code and its own exact dependency pins.

Use Node 22.6 or newer. Install this exact starter cohort in your app folder:

npm install --save-dev --save-exact @volter/world@3.0.158 @volter/world-core@3.0.148 @volter/world-runtime@3.0.156 @volter/world-console@3.0.149 @volter/twin-upstash@1.0.2

In your app’s folder, initialize a World with this implementation:

./node_modules/.bin/volter world init --name my-app --twins upstash --source upstash=@volter/twin-upstash

Review the detected vendor and retain the generated bindings. The upstash service’s source must select this version:

{
  "source": {
    "package": "@volter/twin-upstash",
    "version": "1.0.2"
  }
}

This is the source field, not a complete config. Keep the installed version, lockfile and generated service source in agreement. Use the release README for throwaway SDK credentials, seeds and limits.

The assessment records its own earlier tool versions under Measurements. This setup uses the current starter cohort.

Run your app’s own test command inside the World:

./node_modules/.bin/volter world up
./node_modules/.bin/volter world run -- npm test
./node_modules/.bin/volter world log
./node_modules/.bin/volter world down

down stops compute and retains state.

Versions and implementations

Package / versionPublisherStatusFirst use
@volter/twin-upstash1.0.2volter-aiSelected defaultPassed
@volter/twin-upstash1.0.1volter-ailiveNot measured

Evidence for 1.0.2

Installed first use · Passed
Installed first use
Passed
Fresh app installation
Verified
Workflow scope
Exact installed artifact; normal CLI initialization, unchanged SDK, result assertions and retained-state read-only resume where applicable
Customer SDK versions
@upstash/redis@1.38.2
CLI, kernel and runtime versions
@volter/world@3.0.147 · @volter/world-core@3.0.147 · @volter/world-runtime@3.0.147
World clock
{"mode":"wall"}
Retained-state readback
Verified
Stopped compute
Verified
Customer journey failures
0
API coverage, replay and browser measurements

Counts describe the declared HTTP surface, not separate command tables or other protocols. Consult the release README for those workflows.

Assessment scope
packaged-customer-journey; in-process
Declared HTTP surface
7 served · 118 gaps · 125 declared operations
Exercised HTTP operation coverage
7 / 125 declared operations (5.6%)
Journey steps
307 answered / 380 steps
Replay
Equal across 2 runs
Journey failures
0
Browser target
HTTP customer journey replay through Chromium at each request origin; authored HTTP headers and observed wire responses 153.0.8010.12
HTTP operations exercised through Chromium
7 / 125 declared operations (5.6%)
Chromium journey replay
Equal across 2 runs
Browser response observation
Transport observes status, headers and body, including redirects and Set-Cookie; these are not JavaScript-visible response claims
Application-origin CORS coverage
Not measured
Native cookie-jar coverage
Not measured
DOM coverage
Not measured
Source code coverage
Not measured
State transition coverage
Not measured
Operations not exercised
  • upstash/api:addTeamMember
  • upstash/api:changePlan
  • upstash/api:createBackup
  • upstash/api:createDatabase
  • upstash/api:createIndex
  • upstash/api:createSearchIndex
  • upstash/api:createTeam
  • upstash/api:deleteBackup
  • upstash/api:deleteDatabase
  • upstash/api:deleteIndex
  • upstash/api:deleteSearchIndex
  • upstash/api:deleteTeam
  • upstash/api:deleteTeamMember
  • upstash/api:disableAutoUpgrade
  • upstash/api:disableDailyBackup
  • upstash/api:disableEviction
  • upstash/api:disableQStashProdPack
  • upstash/api:enableAutoUpgrade
  • upstash/api:enableDailyBackup
  • upstash/api:enableEviction
  • upstash/api:enableQStashProdPack
  • upstash/api:enableTls
  • upstash/api:getDatabase
  • upstash/api:getDatabaseStats
  • upstash/api:getGlobalSearchStats
  • upstash/api:getGlobalVectorStats
  • upstash/api:getIndex
  • upstash/api:getQStashIPv4
  • upstash/api:getQStashStats
  • upstash/api:getQStashUser
  • upstash/api:getSearchIndex
  • upstash/api:getSearchIndexStats
  • upstash/api:getTeamMembers
  • upstash/api:getVectorIndexStats
  • upstash/api:listAuditLogs
  • upstash/api:listBackup
  • upstash/api:listDatabases
  • upstash/api:listIndices
  • upstash/api:listQStashUsers
  • upstash/api:listSearchIndexes
  • upstash/api:listTeams
  • upstash/api:moveQStashToTeam
  • upstash/api:moveToTeam
  • upstash/api:renameDatabase
  • upstash/api:renameIndex
  • upstash/api:renameSearchIndex
  • upstash/api:resetIndexPasswords
  • upstash/api:resetPassword
  • upstash/api:resetQStashToken
  • upstash/api:resetSearchPassword
  • upstash/api:restoreBackup
  • upstash/api:setIndexPlan
  • upstash/api:setQStashPlan
  • upstash/api:transferIndex
  • upstash/api:transferSearchIndex
  • upstash/api:updateBudget
  • upstash/api:updateQStashBudget
  • upstash/api:updateRegions
  • upstash/qstash:delete_v2_dlq
  • upstash/qstash:delete_v2_dlq_dlqid
  • upstash/qstash:delete_v2_messages_messageid
  • upstash/qstash:delete_v2_queues_queuename
  • upstash/qstash:delete_v2_schedules_scheduleid
  • upstash/qstash:delete_v2_topics_urlgroupname
  • upstash/qstash:delete_v2_topics_urlgroupname_endpoints
  • upstash/qstash:delete_v2_workflows_dlq
  • upstash/qstash:delete_v2_workflows_dlq_callback_dlqid
  • upstash/qstash:delete_v2_workflows_dlq_dlqid
  • upstash/qstash:delete_v2_workflows_runs
  • upstash/qstash:get_v2_bulkactions
  • upstash/qstash:get_v2_bulkactions_actionid
  • upstash/qstash:get_v2_dlq
  • upstash/qstash:get_v2_dlq_dlqid
  • upstash/qstash:get_v2_flowcontrol
  • upstash/qstash:get_v2_flowcontrol_flowcontrolkey
  • upstash/qstash:get_v2_globalparallelism
  • upstash/qstash:get_v2_keys
  • upstash/qstash:get_v2_keys_rotate
  • upstash/qstash:get_v2_logs
  • upstash/qstash:get_v2_queues
  • upstash/qstash:get_v2_queues_queuename
  • upstash/qstash:get_v2_schedules
  • upstash/qstash:get_v2_schedules_scheduleid
  • upstash/qstash:get_v2_topics
  • upstash/qstash:get_v2_topics_urlgroupname
  • upstash/qstash:get_v2_waiters_eventid
  • upstash/qstash:get_v2_workflows_bulkactions
  • upstash/qstash:get_v2_workflows_bulkactions_actionid
  • upstash/qstash:get_v2_workflows_dlq
  • upstash/qstash:get_v2_workflows_dlq_dlqid
  • upstash/qstash:get_v2_workflows_logs
  • upstash/qstash:patch_v2_schedules_scheduleid_pause
  • upstash/qstash:patch_v2_schedules_scheduleid_resume
  • upstash/qstash:post_v2_batch_trigger
  • upstash/qstash:post_v2_dlq_retry
  • upstash/qstash:post_v2_dlq_retry_dlqid
  • upstash/qstash:post_v2_flowcontrol_flowcontrolkey_pause
  • upstash/qstash:post_v2_flowcontrol_flowcontrolkey_pin
  • upstash/qstash:post_v2_flowcontrol_flowcontrolkey_resetrate
  • upstash/qstash:post_v2_flowcontrol_flowcontrolkey_resume
  • upstash/qstash:post_v2_flowcontrol_flowcontrolkey_unpin
  • upstash/qstash:post_v2_keys_rotate
  • upstash/qstash:post_v2_messages_messageid_retry
  • upstash/qstash:post_v2_notify_eventid
  • upstash/qstash:post_v2_notify_workflowrunid_eventid
  • upstash/qstash:post_v2_queues_queuename_pause
  • upstash/qstash:post_v2_queues_queuename_resume
  • upstash/qstash:post_v2_schedules_destination
  • upstash/qstash:post_v2_schedules_scheduleid_pause
  • upstash/qstash:post_v2_schedules_scheduleid_resume
  • upstash/qstash:post_v2_topics_urlgroupname_endpoints
  • upstash/qstash:post_v2_trigger_workflowurl
  • upstash/qstash:post_v2_wait_eventid
  • upstash/qstash:post_v2_workflows_dlq_callback_dlqid
  • upstash/qstash:post_v2_workflows_dlq_restart
  • upstash/qstash:post_v2_workflows_dlq_restart_dlqid
  • upstash/qstash:post_v2_workflows_dlq_resume
  • upstash/qstash:post_v2_workflows_dlq_resume_dlqid
Conformance results
  • decided: 0 failures · every served operation is decided with its demand; every demanded and every refreshed operation is served
  • published: 0 failures · what a release publishes holds every unit: its manifest, its spec and its journeys
  • cited: 0 failures · every vendor fact cited is recorded as a page that answered, each quote found on it
  • refresh: 0 failures · every stored resource of a vendor-backed unit declares how it is read back, and a unit that sends events ingests the vendor's
  • registered: 0 failures · a vendor-backed unit, lane or not, reaches the registered pack's state system
  • allowance: 0 failures · a rate budget above the fallback rests on the vendor's documented allowance, cited in its manifest
  • client: 0 failures · driven by the vendor's own client (its official SDK), served as a World runs it, the vendor's documented behaviour holds · 4 case(s) through the vendor's client
  • life: 0 failures · the life walked over HTTP against the pack served as a World runs it, with its scenario: every check held
  • standalone: 0 failures · served by its server.ts as a World runs it, the pack answers HTTP and the boot probe, and each declared socket upgrades
Publisher, admission and provenance
Source commit
aa8fdf214742cc2bd955d7a5d9d297a995726258
Catalog record commit
7a5a73e10f6b58ac7d2bb0de012d884c99ea6bdd
Package integrity
sha512-jBiFNZf61XrJAhw2uwEqYkHy3aBjnLBvwI7uS6kluqE0knPZ6Uey4yuF459aacY9d0565oCUguI31A2pF2S8HQ==
Admission mode
Trusted internal publisher · maintainer merge
Catalog assessment
Bundled report checksum verified
Assessed at
Not recorded
Assessment input head
6736767c0fb7df6622c9c0dc909374f2a0296685

Read the catalog snapshot

Catalog snapshot · @volter/twin-catalog@0.2.62
Source commit
2d891e44624083a0ee54c058f1a566f050f38f1e
Catalog digest
72cc7d129522aaa089c84552b9d0839ab4cb0924ee7bd56ab359f827cddaa258
Installer integrity
sha512-MelxBw6h8W8k67EMu7SlYXOPwg8Z0QVcpDNKEcMzB8gH4v0JfYK2vuL7WdXNY1epjPZqxyK/5pEvDCiRqU0nAA==

Snapshot identity and measurements