Skip to content

PA space is per-user with a swappable agent: give Assistant Studio a backing store + role-derived access #2160

Description

@jaylfc

The PA space is per-user, and the agent staffing it is swappable

Jay, 2026-07-27. Settles a question that blocked both Jay and @Hermes tonight:
the personal assistant does not get a project in the Projects app.

Why not a project

A PA's world is a journal, a calendar, tasks and deliverables for one person.
A project is a board with members, cards and a repo. Forcing the PA into Projects
means inventing a fake project whose semantics do not fit - which is exactly why
the project picker had nothing sensible to offer when Jay tried to link an
auth-request to "the PA".

The model

One PA space per USER. The agent staffing it is swappable. The space belongs
to the human; whoever holds the @taOS-PA role works in it. Rotating the role
changes who staffs the space and changes nothing about its contents - that is the
entire point of keying on the user.

Current state (verified, not assumed)

desktop/src/apps/AssistantStudioApp.tsx is 704 lines and already models the
right shapes - JournalEntry, Task, CalEvent, Deliverable. But it reads
only /api/agents and persists everything else in localStorage. So today it
is a browser-local UI: the PA's memory dies with a browser profile, and no agent
can read or write any of it. There is no server-side owner of a PA's data.

What this needs

  1. A backing store keyed on user_id, holding journal, tasks, calendar and
    deliverables. Follow the existing BaseStore SCHEMA/MIGRATIONS convention.
  2. Migrate what is in localStorage rather than abandoning it - nothing is
    deleted.
  3. Read/write API the app and the PA agent both use, so the human and the
    agent see one space rather than two copies.

The access rule, and it is the interesting part

Access is derived from the ROLE BINDING at request time, not from a granted
scope.
The question asked on every request is "are you currently the holder of
@taOS-PA for this user?" - not "were you once given pa_read?".

This matters because scope grants cannot currently be revoked (#2148). If PA
access were a normal grant, every former PA would keep access to a user's private
journal forever, and rotating the role would silently accumulate people who can
read it. Role-derived access sidesteps that entirely: stop holding the role, stop
having access, no revocation required.

That property is worth preserving even after #2148 ships a revoke path.

Boundaries

  • The PA space is private to its user. Not a shared surface, not a project,
    no member list.
  • A PA agent may act in exactly one user's space at a time - the one whose role
    it holds.
  • Role routing (Role handles: address a role (@taOS-PA), deliver to whoever holds it #2155) stays separate: it decides who receives a message
    addressed to @taOS-PA. This issue decides where that agent then works.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions