@volter/twin-upstash
Upstash
Deterministic Upstash Redis over REST, rate-limit client calls, and QStash workflows; no live Upstash calls.
Publisher README included in @volter/twin-upstash 1.0.1. Setup gives the installation instructions for this selected 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
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.68 @volter/twin-upstash@1.0.1
npx volter world init --name my-app --twins upstash --source upstash=@volter/twin-upstash
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.
npx volter world up
npx volter world run -- npm test
npx volter world log
npx 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.
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"]),/pipelineand/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. - 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 ownUpstash-Callback-*/Upstash-Failure-Callback-*options; batch; enqueue into a queue, and a queue's upsert; the token as a bearer header orqstash_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 anUpstash-Timeoutonly shortens). Once out of retries, or answered 489 withUpstash-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.
- 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
- 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
Use Node 22.6 or newer. Install the CLI, then the exact packages shown alongside:
npm install -g @volter/world@3.0.108In your app’s folder, initialize a World with this implementation:
volter world init --name my-app --twins upstash --source upstash=@volter/twin-upstashReview 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.1"
}
}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.
Run your app’s own test command inside the World:
volter world up
volter world run -- npm test
volter world log
volter world downdown stops compute and retains state.
Versions and implementations
| Package / version | Publisher | Status | First use |
|---|---|---|---|
| @volter/twin-upstash1.0.1 | volter-ai | Selected default | Not measured |
Evidence for 1.0.1
Installed first use · Not measured
Installed first use was not measured for this release. HTTP coverage and publisher trust do not establish this result.
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:addTeamMemberupstash/api:changePlanupstash/api:createBackupupstash/api:createDatabaseupstash/api:createIndexupstash/api:createSearchIndexupstash/api:createTeamupstash/api:deleteBackupupstash/api:deleteDatabaseupstash/api:deleteIndexupstash/api:deleteSearchIndexupstash/api:deleteTeamupstash/api:deleteTeamMemberupstash/api:disableAutoUpgradeupstash/api:disableDailyBackupupstash/api:disableEvictionupstash/api:disableQStashProdPackupstash/api:enableAutoUpgradeupstash/api:enableDailyBackupupstash/api:enableEvictionupstash/api:enableQStashProdPackupstash/api:enableTlsupstash/api:getDatabaseupstash/api:getDatabaseStatsupstash/api:getGlobalSearchStatsupstash/api:getGlobalVectorStatsupstash/api:getIndexupstash/api:getQStashIPv4upstash/api:getQStashStatsupstash/api:getQStashUserupstash/api:getSearchIndexupstash/api:getSearchIndexStatsupstash/api:getTeamMembersupstash/api:getVectorIndexStatsupstash/api:listAuditLogsupstash/api:listBackupupstash/api:listDatabasesupstash/api:listIndicesupstash/api:listQStashUsersupstash/api:listSearchIndexesupstash/api:listTeamsupstash/api:moveQStashToTeamupstash/api:moveToTeamupstash/api:renameDatabaseupstash/api:renameIndexupstash/api:renameSearchIndexupstash/api:resetIndexPasswordsupstash/api:resetPasswordupstash/api:resetQStashTokenupstash/api:resetSearchPasswordupstash/api:restoreBackupupstash/api:setIndexPlanupstash/api:setQStashPlanupstash/api:transferIndexupstash/api:transferSearchIndexupstash/api:updateBudgetupstash/api:updateQStashBudgetupstash/api:updateRegionsupstash/qstash:delete_v2_dlqupstash/qstash:delete_v2_dlq_dlqidupstash/qstash:delete_v2_messages_messageidupstash/qstash:delete_v2_queues_queuenameupstash/qstash:delete_v2_schedules_scheduleidupstash/qstash:delete_v2_topics_urlgroupnameupstash/qstash:delete_v2_topics_urlgroupname_endpointsupstash/qstash:delete_v2_workflows_dlqupstash/qstash:delete_v2_workflows_dlq_callback_dlqidupstash/qstash:delete_v2_workflows_dlq_dlqidupstash/qstash:delete_v2_workflows_runsupstash/qstash:get_v2_bulkactionsupstash/qstash:get_v2_bulkactions_actionidupstash/qstash:get_v2_dlqupstash/qstash:get_v2_dlq_dlqidupstash/qstash:get_v2_flowcontrolupstash/qstash:get_v2_flowcontrol_flowcontrolkeyupstash/qstash:get_v2_globalparallelismupstash/qstash:get_v2_keysupstash/qstash:get_v2_keys_rotateupstash/qstash:get_v2_logsupstash/qstash:get_v2_queuesupstash/qstash:get_v2_queues_queuenameupstash/qstash:get_v2_schedulesupstash/qstash:get_v2_schedules_scheduleidupstash/qstash:get_v2_topicsupstash/qstash:get_v2_topics_urlgroupnameupstash/qstash:get_v2_waiters_eventidupstash/qstash:get_v2_workflows_bulkactionsupstash/qstash:get_v2_workflows_bulkactions_actionidupstash/qstash:get_v2_workflows_dlqupstash/qstash:get_v2_workflows_dlq_dlqidupstash/qstash:get_v2_workflows_logsupstash/qstash:patch_v2_schedules_scheduleid_pauseupstash/qstash:patch_v2_schedules_scheduleid_resumeupstash/qstash:post_v2_batch_triggerupstash/qstash:post_v2_dlq_retryupstash/qstash:post_v2_dlq_retry_dlqidupstash/qstash:post_v2_flowcontrol_flowcontrolkey_pauseupstash/qstash:post_v2_flowcontrol_flowcontrolkey_pinupstash/qstash:post_v2_flowcontrol_flowcontrolkey_resetrateupstash/qstash:post_v2_flowcontrol_flowcontrolkey_resumeupstash/qstash:post_v2_flowcontrol_flowcontrolkey_unpinupstash/qstash:post_v2_keys_rotateupstash/qstash:post_v2_messages_messageid_retryupstash/qstash:post_v2_notify_eventidupstash/qstash:post_v2_notify_workflowrunid_eventidupstash/qstash:post_v2_queues_queuename_pauseupstash/qstash:post_v2_queues_queuename_resumeupstash/qstash:post_v2_schedules_destinationupstash/qstash:post_v2_schedules_scheduleid_pauseupstash/qstash:post_v2_schedules_scheduleid_resumeupstash/qstash:post_v2_topics_urlgroupname_endpointsupstash/qstash:post_v2_trigger_workflowurlupstash/qstash:post_v2_wait_eventidupstash/qstash:post_v2_workflows_dlq_callback_dlqidupstash/qstash:post_v2_workflows_dlq_restartupstash/qstash:post_v2_workflows_dlq_restart_dlqidupstash/qstash:post_v2_workflows_dlq_resumeupstash/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
- Publisher
- volter-ai/twin-packs-open
- Source commit
- ef7378d7523ac2c449ccecff170e7ee79aa9234e
- Catalog record commit
- 074e3dcdd99b647c1e9abb8b696604cf6a0570a7
- Package integrity
sha512-/0qbzpyAMt+lRa5Cl4+hgCRCGH5fSxWiD0bY4Haj5yZD6Y4W+67LQRllb5wUiYsqkSE33HOn5nbkvzUwMix9JA==- Admission mode
- Trusted internal publisher · maintainer merge
- Catalog assessment
- Bundled report checksum verified
- Assessed at
- Not recorded
- Assessment input head
- 15110effcd1b01a61954b9bc613a3ed528a321fe
- Evidence
- Assessment and admission
Catalog snapshot · @volter/twin-catalog@0.2.41
- Source commit
a4c5e0664985a7f5a173b58cd307b88a7ddd2795- Catalog digest
5103e721dd9632a05ec4d5348d1b9e668ee092b3edf634c0e4b08f08efb76527- Installer integrity
sha512-uadY72Kz68IvyrNGcUCyJIOXAPQJz9dsyUgG7DUpTVFgZNseWyEQ1We/cSDi4Z9gPtd11owQAJ3EtAuIutcSQw==