Skip to content

feat(auth): multi-user foundation with admin, shares, and WebUI bootstrap - #815

Open
nicolaeser wants to merge 1 commit into
iOfficeAI:mainfrom
nicolaeser:feat/multi-user-foundation
Open

feat(auth): multi-user foundation with admin, shares, and WebUI bootstrap#815
nicolaeser wants to merge 1 commit into
iOfficeAI:mainfrom
nicolaeser:feat/multi-user-foundation

Conversation

@nicolaeser

Copy link
Copy Markdown

Summary

Phase-1 multi-user foundation for team WebUI hosting.

Features

  • Site roles (admin | member) with last-admin invariant
  • Bootstrap admin credentials file for WebUI first boot
  • Admin user APIs — create/update role/status, reset password, revoke sessions, audit log
  • Resource collaboration — share conversations, providers, and projects with view | edit
  • Owner-scoped ACL across conversation/project/provider repositories and services
  • Migrations 038040 (identity foundation, assistant user scope, resource shares)

Tests

  • aionui-auth route tests (48) including admin member password-change flow
  • aionui-auth share route tests (3)
  • aionui-db resource share repository tests (3)

Version

Workspace version bumped to 0.1.64 to align with AionUi pin (aioncoreVersion: v0.1.64).

Related

Companion AionUi PR: iOfficeAI/AionUi#3960

Test plan

  • cargo test -p aionui-auth --test route_tests
  • cargo test -p aionui-auth --test share_route_tests
  • cargo test -p aionui-db --test resource_share_repository
  • Full just check / CI workspace gate
  • Live WebUI multi-user smoke with AionUi compose

…trap

Add site roles, bootstrap admin credentials, resource collaboration
shares for conversations/providers/projects, and owner-scoped ACL across
auth, db, conversation, project, and provider paths for team WebUI hosting.
@nicolaeser

Copy link
Copy Markdown
Author

Status note

CI: GitHub Actions has not reported checks on this fork PR yet (typical for first-time fork contributions until a maintainer clicks Approve and run workflows).

Version: workspace bumped to 0.1.64 so AionUi can pin multi-user once released. Companion UI PR: iOfficeAI/AionUi#3960

Local verification already run:

  • cargo test -p aionui-auth --test route_tests (48 passed)
  • cargo test -p aionui-auth --test share_route_tests (3 passed)
  • cargo test -p aionui-db --test resource_share_repository (3 passed)

Please approve Actions for this PR so full workspace CI can run.

kaizhou-lab added a commit that referenced this pull request Aug 14, 2026
…ge (#855)

## Problem

Migration 031 seeded omp as `npx -y @oh-my-pi/pi-coding-agent acp` with
`binary_name: "omp"`, copying the shape the Registry-listed npx rows
use. That shape does not fit omp, and the row ended up paying both
launch paths' costs while getting neither's benefit.

**There is no Registry entry to conform to.** Audited against the public
ACP Registry catalogue: 11 of the 13 `command='npx'` builtin rows match
their Registry entry's package and args *exactly*.

| backend | Registry-declared distribution | our args | match |
|---|---|---|---|
| autohand | npx `@autohandai/autohand-acp` | `-y
@autohandai/autohand-acp` | ✅ |
| codebuddy | npx `@tencent-ai/codebuddy-code` `--acp` | `-y --package …
codebuddy --acp` | ✅ |
| deepagents | npx `deepagents-acp` | same | ✅ |
| dimcode | npx `dimcode acp` | same | ✅ |
| dirac | npx `dirac-cli --acp` | same | ✅ |
| glm-acp-agent | npx `glm-acp-agent` | same | ✅ |
| grok | npx `@xai-official/grok agent stdio` | same | ✅ |
| kilo | npx `@kilocode/cli acp` | same | ✅ |
| nova | npx `@compass-ai/nova acp` | same | ✅ |
| pi | npx `pi-acp` | same | ✅ |
| sigit | npx `@smbcloud/sigit` | same | ✅ |
| **mimo-code** | *not listed* | — | non-Registry builtin |
| **omp** | *not listed* | — | non-Registry builtin |

For the 11, npx **is** the vendor's declared ACP distribution and
bridging is correct — this PR does not touch them. omp is one of the two
non-Registry builtins, so its bridge was chosen by analogy rather than
from a declared distribution.

**And the package is not an adapter.** `@oh-my-pi/pi-coding-agent` ships
`bin: {omp: dist/cli.js}`; `omp acp` is the vendor's own entrypoint
(`packages/coding-agent/src/commands/acp.ts`, built on
`@agentclientprotocol/sdk`), and the vendor publishes standalone
binaries per release. Contrast `pi-acp` ("ACP adapter for pi coding
agent") or `@autohandai/autohand-acp` ("ACP adapter for the Autohand
CLI"), where `binary_name` names a *different* CLI the package wraps and
the PATH gate is genuinely required.

**The local binary was already mandatory.** `binary_name: "omp"` makes
`probe_resolved_command` fail the row with `PrimaryMissing` when `omp`
is absent, and `cli_probe::validate_with_budget` already runs the local
`omp --version`. Confirmed on a simulated clean machine (`HOME` pointed
at an empty dir, minimal `PATH`):

```
c9e8a2f4   omp   Builtin   missing   CLI `omp` not on $PATH
```

So the row required a local install, probed it, executed it — and then
spawned a *different* copy through npx.

**What that cost**, spawn to `initialize` response:

| | cold npx cache | warm | local CLI |
|---|---|---|---|
| omp | **81.0s** | 10.0s | **0.7s** |

81s on a fast link, against a 30s handshake budget — the failure
reported in iOfficeAI/AionUi#4009.

## What changed

`039_omp_direct_cli_launch.sql` sets `command='omp'`, `args=["acp"]`,
`agent_source_info={"binary_name":"omp"}` (bridge dropped). The
release-lock entry goes with it, and the two lock-count assertions fall
to 12.

**Written as an UPDATE, not a re-seed.** `agent_capabilities` and
`auth_methods` hold what a live handshake learned on the user's own
install; an `ON CONFLICT DO UPDATE` that lists them resets that to an
integration-time snapshot (dead code on a fresh row, silent data loss on
an existing one — the migration-023 shape). An UPDATE of the launch
columns cannot reach those columns at all, so the guarantee is
structural rather than review-dependent.

## Verification

Real-path check, doctor run from this branch's build against a freshly
migrated DB:

```
before:  c9e8a2f4  omp  Builtin  available  npx
after:   c9e8a2f4  omp  Builtin  available  /Users/zhoukai/.bun/bin/omp
```

Catalogue still 43 rows, availability unchanged at 41/2, and `pi` /
`mimo-code` still resolve to `npx` — the change is scoped to omp. Seeded
row after 039:

```
omp|omp|["acp"]|{"binary_name":"omp"}|[".omp/skills",".claude/skills"]
```

- `cargo test -p aionui-db -p aionui-runtime -p aionui-ai-agent` — all
green (331 / 12 suites / 939 + 38)
- `cargo clippy` on those three with `-D warnings` — clean
- `cargo fmt --all -- --check` — clean
- `just migration-check` — passed
- Written test-first: both row assertions were watched failing for the
right reason (`command` was `Some("npx")`; the lock still carried omp).
The third test is a guard that passes before and after — its job is to
catch a re-seed clobbering the probed handshake columns.
- Local workspace `nextest` not run (work-hours policy); CI's Test check
is the authority.

## Trade-off

omp's version is no longer pinned by `acp-registry-npx-lock.json` — it
now tracks whatever the user has installed, exactly as the other
direct-CLI builtins (qwen, agy) do. Version upkeep moves to the
`VERIFIED_*` path.

## Not in scope

- **The other 12 npx rows stay.** For the 11 Registry-listed ones, npx
is the declared distribution and bridging is correct as-is.
`glm-acp-agent` is a different shape again — a pure ACP package with no
separate product CLI, whose `binary_name` gate looks questionable but
which should *drop the gate*, not go direct; left for its own change
with its own evidence.
- **mimo-code stays on npx.** Same non-Registry status, but its cold
start is 16.0s (warm 3.6s) — inside the budget, so there is no failure
to fix. Its npm package is a launcher that resolves a 95 MB platform
binary, and the vendor's postinstall recommends a native install over
npm; that is worth revisiting, but not under a bug fix.
- **Install-path detection.** `platform_extra_bins()` covers
`.cargo/bin`, `go/bin`, `.deno/bin`, `.local/bin`, `.volta/bin` and nvm
— but not `~/.bun/bin` (where omp lands via bun) or `~/.mimocode/bin`
(where mimo's own installer puts it). A user who follows the vendor's
install and lacks that directory in their login-shell PATH still gets a
hidden row. That is the broader half of AionUi#4009 proposal 1 and
affects every agent, so it belongs in its own change.

## Migration number 039 is contested

`039` is currently claimed by three open PRs — this one, #644
(`039_project_knowledge.sql`) and #815
(`039_user_scope_assistant_ids.sql`) — and `038` is likewise claimed by
#815, #644 and the sidebar stack. Whichever lands first takes the
number; the others must rebase and rename.

This is caught, not silent: `scripts/migration/check-immutability.sh`
rejects duplicate numeric prefixes. Verified by putting both 039 files
in a scratch checkout of `main`:

```
Duplicate database migration versions are not allowed.
Duplicate versions:
39: 039_project_knowledge.sql, 039_omp_direct_cli_launch.sql
```

(exit 1). So if another 039 merges first, this PR's CI turns red on
rebase and the fix is a one-file rename — no risk of two different
`039`s reaching a release. Renumbering pre-emptively would not help:
#644 also claims `040` and `041`.

Closes iOfficeAI/AionUi#4009

Scope note on that link: the issue's timeout and npm-cache halves are
covered (the first by #854, the second already
shipped), and its primary ask — use the installed omp instead of forcing
npx — is what this PR does. What it does NOT add is a scan of extra
install locations such as `%LOCALAPPDATA%\omp`: detection still goes
through the app's resolved PATH, so an omp that is installed but not on
PATH stays hidden. That gap is agent-agnostic and tracked separately.

Co-authored-by: zk <>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant