Install visibility: debug vs production
An app_id is globally unique - there is exactly one install row
per app_id on a daemon, never one row per user. What Digitorn
actually gives you at install time is a visibility state
machine (production / debug) plus an owner, and it exists
for one purpose: letting you test a build in Studio before anyone
else can see it.
| Visibility | Set by | Who sees it | Who can run it |
|---|---|---|---|
production (default) | Any install that doesn't request debug | Everyone on the daemon | Everyone |
debug | Studio's Install for Test | Only the owner (and admins) | Only the owner (and admins) |
This is the same debug/production distinction documented in Digitorn Studio
- this page is the mechanism behind it, not a separate feature.
What "owner" means here
Installing sets owner_user_id from the caller's JWT automatically
- there's no request field to choose it. A
debuginstall requires an owner (the daemon rejects an anonymous debug install); aproductioninstall can have an owner or not.
// POST /api/apps/install
{
"source": "https://.../my-app.yaml",
"accept_permissions": true
}
That's the whole request shape - source and (for Hub sources
that need a consent step) accept_permissions. There's no scope
field, no source_type/source_uri split, and no CLI flag to
request a particular visibility: digitorn install always installs
at production. Only Studio's own install action can request
debug.
The debug → production lifecycle
- Install for Test (Studio) installs the app at
debug, owned by the person testing it. It's invisible to everyone else - the default app listing hidesdebuginstalls entirely, and even an explicit lookup by ID returns "not found" for anyone but the owner. - Publish (Studio) promotes that same row from
debugtoproduction- a same-row flip, not a second install. Only the owner can promote it. Once promoted, everyone on the daemon can see and run it, and the app stays associated with that owner for?mine=1filtering afterward.
Because there's one row per app_id, a few conflicts are
enforced when you install again:
- You can't
debug-install over anapp_idthat's alreadyproduction(refused as a conflict). - You can't
debug-install anapp_idsomeone else already holds atdebug(refused as forbidden). - You can't
production-install over anapp_idsomeone else owns, unless you're that app's publisher.
Listing your own installs
GET /api/apps?mine=1 # only your own installs (debug + production)
GET /api/apps # production installs, everyone's
GET /api/apps?include_debug=1 # also show debug installs (tooling)
What this is not
There's no per-user private copy of a shared app: if you want
each user to get their own isolated instance of the same
template, that's a separate install per app_id you'd have
to name differently per user - the daemon has no built-in
mechanism for one app_id to resolve to different definitions
depending on who's asking.
Isolation within one shared app instance - so concurrent users of the same production app don't see each other's data - comes from two unrelated mechanisms:
- Per-user credentials -
credential.scope: per_userstores a secret encrypted per(user_id, provider)- the only scope with real behavior today, see credentials.md. - Per-session memory - goals, facts, and tasks are keyed by session id, and a session belongs to one user, so two users' sessions never share state. See Cognitive Memory.
Cross-references
- The Studio workflow this mechanism backs: Digitorn Studio → Install for Test vs Publish
- Per-user credentials (a different, unrelated per-user concept): credentials.md
- Per-session memory isolation: Cognitive Memory