Skip to content

Make app-job authority explicit - #311

Merged
hamzamerzic merged 3 commits into
mobius-os:mainfrom
rgjordana:fix/background-job-contract-cleanup
Jul 28, 2026
Merged

Make app-job authority explicit#311
hamzamerzic merged 3 commits into
mobius-os:mainfrom
rgjordana:fix/background-job-contract-cleanup

Conversation

@rgjordana

@rgjordana rgjordana commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Why this change exists

Möbius can run reviewed app scripts outside the browser. Some jobs retain the
operating-system authority of the Möbius process. Others are confined to a
smaller set of reviewed app resources through Bubblewrap or Landlock.

The manifest previously selected the confined form with
permissions.background_agent: true. That name described a possible
implementation detail, not the security decision:

  • a platform-authority job may run an AI agent;
  • a scoped job may run deterministic code;
  • scheduling and embedded-agent UI are separate concerns.

This PR names the actual decision directly, makes the normalized receipt agree
with it, and rejects malformed or stale declarations instead of silently
running them with broader authority.

What we audited

The current official catalog contains 18 apps and 10 server-side jobs. Only
Memory declares background_agent: true; the other nine jobs retain the
historical platform authority by omission. Code and installed-app searches
found no second official scoped consumer.

The same phrase also appears in the platform's background AI model settings.
Those settings choose provider/model pairs for unattended agents and are a
separate concept. They are intentionally unchanged.

The App Store repository also contains a generated first-paint snapshot of the
current Memory manifest. Its documented update flow deliberately does not
publish a Store release for every app update: install and update review fetch
the live manifest and backend-derived capability receipt. The generated
snapshot will refresh with the next Store catalog refresh and is not install
authority, so this change does not create a third repository dependency.

This makes the public manifest rename small and concrete rather than a general
permission-system redesign.

The authority model

A server-side app job may now declare:

"permissions": { "job_authority": "scoped" }

or:

"permissions": { "job_authority": "platform" }
  • Scoped authority exposes the app's source, storage, declared shared data,
    supported provider credentials, and other reviewed resources through a
    secure executor.
  • Platform authority retains the historical operating-system authority of
    the Möbius process for trusted maintenance jobs.

Omitting job_authority continues to mean platform authority so existing
ordinary jobs do not all require a coordinated migration. New or updated apps
can state either choice explicitly.

This remains intentionally binary because Möbius currently has two real
execution boundaries. Resource-specific nuance belongs inside the scoped
contract; a new resource should not create another tier. A third authority
profile should wait for a demonstrated requirement backed by a materially
different enforcement mechanism.

Remove the stale spelling rather than alias it

permissions.background_agent is removed. A manifest that still uses it fails
with a direct migration message:

use permissions.job_authority: scoped

It is not accepted as an alias and it is not silently ignored. Silent ignore
would be unsafe: Memory would lose the scoped declaration and run with platform
authority.

The companion mobius-os/app-memory#22 change replaces its one boolean
declaration with job_authority: scoped and updates the matching manifest
test. No Memory job code or access requirement changes.

Make the receipt match the public declaration

Capability receipt schema 3 now records:

"background": {
  "authority": "scoped"
}

or "platform" directly. It no longer carries the redundant background-agent
boolean.

The runner resolves one authority before selecting an executor. A missing
receipt field, malformed schema-3 authority, legacy-shaped schema-3 receipt, or
unknown future schema is rejected and logged before child launch.

Preserve installed data without preserving the old API

Existing persistent volumes may still contain:

  • a null pre-contract receipt;
  • a schema-1 receipt;
  • a schema-2 receipt;
  • a known receipt with background: null for a source-discovered local or
    legacy job.

Schemas 1 and 2 used the old boolean plus internal authority label. The runner
continues to accept those stored receipts only when both fields form one of the
two coherent historical pairs, then maps them to scoped|platform. This is
bounded data compatibility, not a second manifest spelling.

Newly generated receipts use schema 3. Unknown future schemas fail closed so a
future contract change must update the launcher deliberately.

Release ordering

The platform and mobius-os/app-memory#22 changes are coordinated across two
repositories:

  1. merge/deploy the platform support;
  2. immediately merge the Memory manifest migration.

Platform-first is fail-closed: already-installed Memory continues running from
its coherent schema-2 receipt, while an old Memory package is rejected on a new
install or update until the companion manifest lands.

Memory-first is not safe on an older platform because that platform does not
understand the new permission name and could ignore it. The two changes should
therefore be reviewed together and released in platform-first order rather
than treated as independent features.

What the scoped boundary protects

Both secure executors apply the same reviewed filesystem policy:

  • app source is readable but not writable;
  • app storage is writable;
  • only declared shared data and supported provider credentials are exposed;
  • the platform checkout, database, service token, other apps, and undeclared
    shared data remain unavailable.

They also block sibling signals and direct memory or file-descriptor
inspection. Bubblewrap provides private PID and mount namespaces when the host
supports them. Landlock does not create a private PID namespace and is
therefore not identical to Bubblewrap.

Möbius is a single-owner system running reviewed internal app code. This
boundary reduces data exposure. It is not a hostile multi-tenant container, a
CPU or memory quota, or complete process-tree isolation.

The documentation also narrows the Landlock socket claim to observed behavior:
it blocks addressable pathname or abstract UNIX endpoints, while private
socketpair(AF_UNIX, ...) IPC remains possible.

Alternatives considered

  • Keep background_agent and only explain it: smallest code diff, but the
    public contract would remain misleading after we verified it has one official
    consumer.
  • Accept both names temporarily: easier release sequencing, but creates two
    public spellings and makes removal someone else's future migration.
  • Require every job to declare an authority immediately: maximally explicit,
    but forces nine unrelated official app migrations and breaks existing
    third-party jobs without improving the one scoped boundary being changed.
  • Add more authority tiers or a general executor registry: no demonstrated
    third enforcement boundary justifies that machinery.

The chosen change removes the misleading public name now, keeps stored receipts
readable, and leaves resource permissions composable.

Commit structure

  1. Document explicit app-job authority — the two boundaries, public
    vocabulary, executor guarantees, compatibility, and evolution rules.
  2. Validate explicit app-job authority receipts — schema-3 production,
    legacy receipt mapping, stale-manifest rejection, and regression tests.
  3. Tighten app-job authority documentation — records why the portable
    contract currently needs two private executor adapters, states their
    asymmetries and removal criteria, and separates cheap launch probes from
    adversarial and deployment-level verification.

The companion Memory repository has one focused commit containing only its
manifest version, declaration, and test update.

Verification

Platform:

  • python3 -m py_compile for the capability producer, manifest validator,
    launcher, and sandbox module;
  • 69 focused backend tests passed, with 1 Bubblewrap integration skipped on the
    namespace-restricted host;
  • the real Landlock integration passed;
  • the previously time-sensitive activity regression passed three consecutive
    runs on the rebased branch;
  • the installed schema-2 Memory receipt resolves to scoped authority with the
    new launcher;
  • the old Memory manifest fails with the intended migration message;
  • the new Memory manifest produces schema 3 with authority: scoped and no
    agent boolean;
  • the candidate platform validator accepts the companion Memory manifest;
  • git diff --check.

Memory companion:

  • 46 JavaScript tests passed;
  • all offline-harness phases passed;
  • 67 Python tests passed;
  • shell and Python syntax checks passed;
  • the candidate platform validator accepts the migrated manifest;
  • git diff --check.

Scope

This changes the manifest vocabulary and normalized job-authority receipt. It
does not change filesystem allowlists, executor preference, schedules,
credentials, Memory behavior, provider/model settings, or the single-owner
threat model. It closes the stale naming path without adding a permanent alias
or pre-designing authority profiles that do not exist.

@rgjordana rgjordana added area: backend Server and API behavior maintenance Internal cleanup, dependency, or upkeep work labels Jul 28, 2026
@rgjordana
rgjordana force-pushed the fix/background-job-contract-cleanup branch from e00ba94 to c7bb2a4 Compare July 28, 2026 14:16
@rgjordana rgjordana changed the title Clarify background-job isolation guarantees Clarify app-job authority and validate receipts Jul 28, 2026
@rgjordana
rgjordana force-pushed the fix/background-job-contract-cleanup branch from c7bb2a4 to ee82e0e Compare July 28, 2026 14:43
@rgjordana rgjordana changed the title Clarify app-job authority and validate receipts Make app-job authority explicit Jul 28, 2026
rgjordana and others added 3 commits July 28, 2026 16:39
Define platform and scoped authority as the two current execution boundaries, name the manifest choice directly, and record executor limits and receipt compatibility.

Co-authored-by: Möbius Agent <mobius-agent@users.noreply.github.com>
Emit schema-3 receipts with direct scoped or platform authority, reject the removed manifest boolean, preserve coherent stored schema-1/2 receipts, and fail closed on malformed context.

Co-authored-by: Möbius Agent <mobius-agent@users.noreply.github.com>
Co-authored-by: Möbius Agent <mobius-agent@users.noreply.github.com>
@rgjordana
rgjordana force-pushed the fix/background-job-contract-cleanup branch from ee82e0e to a303421 Compare July 28, 2026 16:43
@hamzamerzic
hamzamerzic added this pull request to the merge queue Jul 28, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jul 28, 2026
@hamzamerzic
hamzamerzic added this pull request to the merge queue Jul 28, 2026
Merged via the queue into mobius-os:main with commit 94e2fe7 Jul 28, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: backend Server and API behavior maintenance Internal cleanup, dependency, or upkeep work

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants