GurtOSat Cal Hacks 13.0

Agentic Workforce Challenge, Track 2 (security for agents acting for a user)

See what an agent did in Jira, then roll back only that

Every task an agent runs on a GurtOS box becomes a Jira issue with what it was asked, what it was allowed, its reasoning, every blocked attempt, its diff and its full action log. A Forge app adds a panel to the issue with Approve, Deny and Roll back, and Roll back removes only that task's changes on the box.

Proof BOX-2, a scripted agent that misread a rule, changed three configs instead of one and tried to send the repo to a paste site. It was blocked, approved from Jira, then rolled back from Jira: its configs came back and the README fix another task made a minute earlier stayed.

Undo one task. A task deleted notes.md by mistake; Undo task removes only that task's layer, and Time Machine shows the other tasks' layers still in place. Real app, scripted tasks, sped up 1.3 times. Silent screen recording, 31.1 seconds.

What Atlassian asked for

From Atlassian's Track 2 brief and the challenge rules, as copied into the project's track plan.

  1. Audit and reversion: record every action with the inputs and reasoning behind it, so an admin can see exactly what happened the next morning and roll back only the changes that were wrong.
    Met

    Each issue holds the prompt, the tools and hosts the task was allowed, the agent's reasoning in its own words, approvals and who gave them, blocked attempts, the diff and the last 40 log entries. Roll back this task takes out that task's layer of file changes on the box. Every other task keeps its own.

  2. A Forge app for Jira or Confluence.
    Met

    A Jira issue panel (UI Kit, native render) with a resolver in Atlassian's cloud, plus a jira:entityProperty index so state, cost, blocked attempts and pending approvals are searchable in JQL. Installed on the demo site in production.

  3. Technical use of Forge.
    Met

    The resolver reads the issue property as the signed-in user, checks EDIT_ISSUES before any action, and is the only place that holds the box's shared secret (a Forge encrypted variable). It calls one declared external host. Scopes are read-only: the app never writes to Jira; the box does.

  4. Usefulness to Atlassian users.
    Met

    The morning-after question is one JQL search: project = BOX AND boxBlocked > 0. Agent work moves across a normal board (To Do, In Progress, In Review, Done), so a team reviews agents the way it reviews people.

  5. Demo video, 3 minutes at most.
    Partly

    Shot list in the repo's docs/videos.md; the video is embedded above once uploaded.

  6. Repo link.
    Met

    The track lives in tracks/jira/ (box side) and tracks/jira/forge/ (the Forge app).

Screenshots

The Box agent task panel in Jira, waiting for an OK, with a blocked attempt to reach paste.example.net and a diff that changed three service configs.
BOX-2 waits for an OK. The agent misread a rule, changed three configs instead of one, and tried to reach a paste site, which the box refused.
The same panel after Roll back: the task is Rolled back and the configs are as they were.
After Roll back: only this task's changes are gone.
A Droid task asks in Jira to spend 3 dollars of test money on a 1 dollar budget.
BOX-5: a Droid task (Claude) asks to spend $3.00 of test money on a $1.00 budget. The box paused it and the request landed in Jira.
The task after approval from Jira, with its reasoning, an audit trail naming the approver, and its diff.
Approved from Jira, it paid, wrote the receipt and finished. The audit trail says who approved.
A box task as a Jira issue: what it was asked, what it could use, its reasoning, files changed with the diff, and the action log.
BOX-1, written by the box from its append-only action log.
A JQL search on the fields the Forge app indexes, listing BOX-2, BOX-3 and BOX-4.
JQL on the indexed fields: every task that tried a blocked host or was rolled back.

Evidence

The merge gate, ./demo, runs this track on every merge. With DEMO_LIVE=jira it runs against the real demo site, then deletes the issues it made. This run passed on Oct 23 on the x86 test VM; BOX-8 and BOX-9 were real issues on the site:

track jira
  ok    DEMO_LIVE=jira: the vault has the Jira site, email and API token
  ok    BOX-8: task A is an issue in Done, with its diff
  ok    BOX-9: task B waits for an OK, in In Review
  ok    BOX-9 holds B's prompt, steps and diff
  ok    BOX-9 has a comment for the blocked attempt on attacker.example
  ok    BOX-9 has a comment asking for the OK
  ok    without the shared secret the panel routes refuse to approve or roll back (401)
  ok    an approval can't be answered through another task's issue
  ok    approved from Jira, task B finished
  ok    rolled back from Jira: B's settings change is gone, A's fix stays
  ok    the panel's audit view shows the block, who approved and the roll back
  ok    BOX-9 says who rolled it back, in a comment and the description
  ok    no vault secret is in anything the box sent to Jira

The same 12 checks pass offline in every ./demo run, the latest on Oct 24 with all 22 sections of the gate (175 checks, 0 failed).

How it works

How it works, step by step
  1. TaskAn agent worksIts own Linux user, its own copy of the files, no keys.
  2. GurtOS coreThe action logEvery step, tool call, approval and blocked host, in order.
  3. GurtOS coreJira track (log reader)Creates or updates one issue per task over Jira REST v3.
  4. OutsideJira issue and Forge panelThe resolver checks the user may edit the issue.
  5. YouApprove, Deny or Roll backThe resolver calls the box with the shared secret.
  6. GurtOS coreThe box actsSame undo and answer as the portal and phone, logged as jira:<name>.
Task
its own Linux user, its own copy of the files, no keys
GurtOS core
the GurtOS service on the box, root, the only part that reads the vault
Outside
a service outside the box
You
a person, on the portal, a phone, Jira or a chat

Into Jira. The box feeds the track every event in its append-only log, in order, and saves its place, so it survives restarts and power cuts. Agent output only ever goes into Atlassian Document Format text nodes, so a task cannot inject markup, links or mentions into Jira. Status follows the task: queued is To Do, running is In Progress, waiting for an OK is In Review, and done, failed or rolled back is Done. It is safe to repeat: a crash between creating an issue and saving its key finds the issue by label instead of making a second one.

Out of Jira. The panel's resolver runs in Atlassian's cloud. It reads the issue's box.task property as the signed-in user (so the task id comes from Jira, never from the browser), asks Jira whether that user may edit the issue, and only then calls the box with the shared secret, passing the user's name for the log. The box checks the secret in constant time and checks that the approval belongs to that task. From the internet, the box forwards only its Jira routes and one read-only status route; the rest of its API is a 404.

Forge or Atlassian piece Used for
jira:issuePanel (UI Kit, native render) The Box agent task panel on BOX issues
@forge/resolver load, answer, rollback
jira:entityProperty JQL fields boxState, boxCost, boxBlocked, boxPending, boxSource
api.asUser().requestJira Reads the property, the user's permissions and name, with the user's own access
fetch with permissions.external.fetch.backend The one call out, to the box
Encrypted variable BOX_SECRET The shared secret
Jira REST v3, from the box issue, properties, transitions, comment, search/jql

Try it

  1. Put ATLASSIAN_SITE, ATLASSIAN_EMAIL, ATLASSIAN_API_TOKEN and JIRA_BOX_SECRET in the box's vault, /etc/box/vault.env.
  2. Turn syncing on: echo '{"project":"BOX"}' > /var/lib/box/jira/config.json.
  3. Give the box public HTTPS for /t/jira/* only (the README has the Caddy block).
  4. From tracks/jira/forge/: forge variables set --encrypt BOX_SECRET <secret>, forge deploy, forge install.
  5. Start any task on the box. Its issue appears in BOX; open the panel and try Approve and Roll back.

The full steps are in the track README and the docs guide Connect Jira.

Live, test and simulated

PartStateDetails
Jira issues, comments, status and JQL fieldsLiveWritten by the box to the demo site's BOX project. DEMO_LIVE=jira ./demo runs the whole flow against the real site.
Forge panel and resolverLiveInstalled in production on the demo site.
The agents behind the issuesLiveBOX-1 and BOX-5 are real Droid tasks running Claude. BOX-2 is a scripted agent, so the misread rule happens the same way every time.
MoneyTest moneyThe coffee order uses the example track's example.spend, which moves no money.
Offline merge gateSimulated./demo points the track at a stand-in for Jira Cloud on the test machine, so every merge runs it without touching the real site.

Limits

  • Roll back undoes the task's file changes. It cannot recall something a task already sent out through a tool, such as a payment. Those show in the issue so a person can follow up.
  • One shared secret guards the box's three Jira routes. Forge Remote's signed invocation tokens would let the box check each call came from this app and this user; that is the next step.
  • The box writes to Jira with one person's API token, so its comments show that person as the author.
  • The panel polls the box every 4 seconds while it is open.
  • Issue descriptions keep the last 40 log entries and the first 8,000 characters of the diff. The panel and the box's log have the rest.
Every track