Skip to main content

Security Model

NIIA is not one universal permission. Memory reads, MCP calls, terminal writes, OS observations, OS actions, and remote transport cross different gates and keep different owners. Documents NIIA 0.9.41.

Built-ins and external packages

Built-in command names do not share a namespace with external packages:
External packages must use the @scope/name form and pass NIIA’s package trust check before their executable is launched. Their output is wrapped with a source boundary so an agent can distinguish package text from NIIA’s own response. Trusting an external package authorizes that package to run with the user’s OS permissions. It is not a sandbox. Do not trust a package from an unknown source.

Signed content trust

niia trust verifies the OpenCLIs trust-domain registry, whose responses are signed with Ed25519. This content-source trust surface is separate from the local external-package allowlist.
“Trusted documentation source” and “authorized local executable” are different claims.

Authentication and secret ownership

Authentication is owned by the current Monosystem/OpenCLIs credential path. NIIA forwards supported lifecycle operations without putting JWTs or policy tokens into child process arguments or ordinary environment variables. An authenticated identity does not automatically grant OS control or authorize every remote operation.

MCP fails closed

Local stdio MCP accepts scalar key=value and explicit structured key:=JSON. Remote REST accepts scalar query arguments only. The following conditions return a non-zero shell exit:
  • MCP isError
  • JSON-RPC or transport failure
  • persistent-session failure
  • explicit quota denial
  • authentication denial
  • remote REST failure
With --json, an MCP isError payload remains on stdout before the non-zero exit so automation gets both evidence and failure status. The supported NIIA server registration is niia mcp. The retired standalone rust-niia-mcp binary is not the current public boundary.

Terminal health and assertions

A rendered terminal frame can outlive the process that produced it. NIIA checks health before treating a session as drivable:
Failed health gates, missing guards, and assertion timeouts return non-zero unless the caller explicitly chooses a documented force path.

Work-entry discipline is advisory

niia gauge, finish, and audit-entry record and report a session contract; they do not become an authorization system. The user’s explicit rung always wins. A [CONSENT] overlay on destructive or live-surface language is a reminder to obtain owner confirmation in the active conversation, not a token that grants the operation. Fan-out is proposal-only. finish writes a close witness even when it re-presents unmet work, and audit-entry never blocks. Hook audit is silent so a SessionEnd/Stop hook does not inject text into the conversation. Witness files can contain task text, repository paths, provider brand, transcript path, and event history; they remain local under .niia/session-order/ or the cwd-hashed home witness path unless the user explicitly transfers them. Hook-internal errors also cannot turn the steering layer into a prompt gate. gauge --hook, gauge --session-start, and audit-entry --hook retain exit zero, report the error on stderr, and append it to ~/.niia/hook-error.log for doctor to surface. Only a session id delivered by hook stdin owns the atomic current pointer; CLI --session and isolated verification runs cannot seize the live session’s close target. niia doctor does not walk or rewrite indexed corpora. It reads timestamps and a bounded log tail. To verify witness-directory writability, it briefly creates and removes .doctor-probe; that ephemeral probe is its only write.

OS grants

NIIA separates observation and control:
Unlock requires human authentication. An AI cannot manufacture the OTP that opens the gate. NIIA owns the grant. Kernel CLI owns the underlying OS operation. Passing a write command through niia observe is rejected; passing a write through niia control still requires the correct grant.

Target handles and stale-state defense

targets creates an AX + OCR interaction map. control act can bind the action to the observed snapshot, reject a stale target, reveal an off-screen element, report the planned write with --dry-run, and verify the result after actuation. This is safer than assuming that coordinates or labels still refer to the same screen state.

Remote execution is deliberately narrow

The daemon-direct exec surface accepts exact diagnostics only: now, status, and --version. Arbitrary argv is rejected before alias resolution or child execution. Use relay operations for terminal work after reachability is proven. File copy uses one exact Headless WebRTC session. Cleanup prints a target-local plan rather than widening gateway execution into a general shell.

Remote updates require scope and a device gate

The dry-run returns openclis.update-plan.v1 and does not stop Headless, install software, or require the mutation gate. Application requires exact tool names or --all plus the target device’s upgrade gate. openclis and openclis-vault are rejected because their keychain approval must be renewed interactively on that machine. The receiver restarts only selected affected runtime, and plan, child, restart, protocol, or timeout failures return non-zero. Legacy niia remote upgrade <machine> updates NIIA only.

Skill drift protection

niia setup does not silently overwrite locally evolved skills and agents.
  • diff reports embedded-versus-installed state.
  • adopt records a baseline without writing installed content.
  • export stages evolved material for deliberate back-porting.
  • destructive replacement requires an explicit force choice.

Browser ownership

MonoSurf operates inside the browser page through CDP. Kernel CLI operates browser chrome, native dialogs, file pickers, Keychain/Face ID prompts, and other apps. NIIA supplies the authorization and orchestration layer when a workflow crosses between them. See complete commands for every gated entrance.