Repository navigation
feat(agents): agent-connect plugin — owner-controlled agent accounts on the NEAR Intents Agent API - #403
Open
elliotBraem wants to merge 22 commits into
Open
feat(agents): agent-connect plugin — owner-controlled agent accounts on the NEAR Intents Agent API#403elliotBraem wants to merge 22 commits into
elliotBraem wants to merge 22 commits into
Conversation
|
🚅 Deployed to the everything-dev-pr-403 environment in heartfelt-ambition
8 services not affected by this PR
|
railway-app
Bot
temporarily deployed
to
heartfelt-ambition / everything-dev-pr-403
October 15, 2026 06:55
Destroyed
elliotBraem
added this pull request to stack #404
October 15, 2026 07:03
… repo path (#392) bos import <workspace> --from <owner/repo>[@ref]|url|dir imports a workspace subtree (e.g. plugins/auth) from an upstream GitHub repo tarball or a local directory, without cloning. Shared files are classified against a per-workspace baseline (.bos/import-snapshot.json, falling back to .bos/sync-snapshot.json) into added / unchanged / updated / preserved-local / preserved-local-edit / merged / conflict buckets; local-only files are never deleted and a diverged package.json is structurally merged instead of overwritten. Unresolvable conflicts — and a migration chain that cannot be applied verbatim (index reuse, content drift, local-only journal entries), which is held back rather than dropped — gate the run: nothing is written without --yes or an interactive confirm, exiting non-zero with a full .bos/import-report.md divergence report (conflict checklist, migration collisions and chain delta, contract route-set delta across both monolithic and split src/contract/** shapes). Successful imports back up overwritten files to .bos/import-backup/, record fresh baselines, and support --dry-run, --no-install, and --json. Closes #392 Refs #393
…0.0-rc.1 The changeset release bumped packages/better-near-auth to 2.0.0-rc.1 (better-auth 1.6.25 → 1.7.7 internal upgrade — no documented API changes), so the six skills' library_version markers drift and the Check Skills workflow fails with needsReview on every PR merge commit. Reviewed via 'intent stale packages/better-near-auth': version bump only, no content regeneration needed.
Applied local journal entries are kept verbatim; colliding upstream migrations are renumbered and appended after the local tail (.sql + meta/*_snapshot.json renamed, journal rebuilt with monotonic when). Repeat imports converge via SQL content-hash matching. ImportResult gains migrationReconciliation (kept/appended/contentMatched); the chain is held back only for unresolvable content drift or an unreadable journal. Appends gate the run behind --yes/confirm like conflicts.
Give every signed-in user an owner-controlled agent account on NEAR Intents: the owner signs the rules once (nep413/nep366 via the connected wallet, webauthn via passkey), agents hold revocable ngt_ grant tokens that only act inside the owner-signed policy. - better-near-auth: server plugin agentConnect (dormant without a naa_ key) wrapping @near-intents-agent-api/sdk behind /agent/* endpoints with session-agent-intent ownership checks, persisted idempotency keys, and encrypted-at-rest grant tokens; client plugin exposes client.agent.* with byte-for-byte intent signing and a one-call signAndSubmitIntent; SDK wire types re-exported, not re-declared - plugins/auth: register agentConnect; drizzle tables agent_account, owner_intent, agent_grant (+ generated migration) - ui/auth: register agentConnectClient; bos.app.ts declares the NEAR_INTENTS_AGENT_API_KEY secret
- persist the owner-intent ledger row (keyed by idempotency key) before the generate call, then link the real correlation id after — the send/persist ordering rule holds across crashes; ledger writes fail loud instead of being swallowed - ownerIntent.grantId held two meanings (local row id for issues, API grant id for revokes); rename to grantRowId and resolve the local row at revoke-creation time so submit updates one uniform key - cross-user correlation ids answer 404 (not 403) — no enumeration leak - type the error-status map as a literal union; drop the lying cast and the dead null parameter in the wallet signer bridge - test the grant-token round trip (encrypt → refuse wrong secret → decrypt) and add GLOSSARY entries for the agent-connect vocabulary
meta/_journal.json is per-workspace and resolves nowhere from the skill file — reword so the docs link check passes on the stacked branch.
elliotBraem
force-pushed
the
feat/agent-connect
branch
from
October 15, 2026 07:15
474afc4 to
905f517
Compare
railway-app
Bot
temporarily deployed
to
heartfelt-ambition / everything-dev-pr-403
October 15, 2026 07:15
Destroyed
The rebase's snapshot/journal resolution clobbered the upstream 0011-0013 entries; restore them verbatim from the base and regenerate the agent-connect migration as 0014 from the merged schema.
elliotBraem
force-pushed
the
feat/agent-connect
branch
from
October 15, 2026 13:53
239a9ae to
8a6c287
Compare
elliotBraem
added a commit
that referenced
this pull request
Oct 15, 2026
…410) ADR 0029 records the three-surface model (connect UX / operating surface / model tools), the two-ledger rule, the permission layering, and the default-deny exposure principle; the durable role of #403's endpoint layer stays open for ticket 16 (ready-for-human). Ticket 17 makes MCP per-tool permission filtering a prerequisite for ticket 13. Sprint graph, ADR index (backfills 0027-0028), and GLOSSARY surface vocabulary updated.
elliotBraem
force-pushed
the
feat/agent-connect
branch
from
October 15, 2026 16:25
8a6c287 to
2ac6eee
Compare
railway-app
Bot
temporarily deployed
to
heartfelt-ambition / everything-dev-pr-403
October 15, 2026 16:25
Destroyed
# Conflicts: # .changeset/bos-import-workspace.md # GLOSSARY.md # packages/everything-dev/skills/cli-reference/SKILL.md # packages/everything-dev/skills/init-upgrade/SKILL.md # packages/everything-dev/src/cli.ts # packages/everything-dev/src/cli/import.ts # packages/everything-dev/src/commands/import.ts # packages/everything-dev/src/contract.meta.ts # packages/everything-dev/src/contract.ts # packages/everything-dev/tests/unit/import-from-spec.test.ts # plugins/auth/src/db/migrations/meta/0014_snapshot.json # plugins/auth/src/db/migrations/meta/_journal.json # plugins/auth/src/db/schema.ts
…nomy design space
elliotBraem
force-pushed
the
feat/agent-connect
branch
from
October 16, 2026 18:49
2ac6eee to
d6fb0cd
Compare
railway-app
Bot
temporarily deployed
to
heartfelt-ambition / everything-dev-pr-403
October 16, 2026 18:49
Destroyed
Move the agent-account control plane out of better-near-auth/plugins/auth into plugins/agent-connect: oRPC contract (agent CRUD, prepare/submit/status intents, grants), Effect services over @near-intents-agent-api/sdk (the only protocol dependency — types re-exported, never re-declared), sealed grant vault, pre-send intent ledger, and an own plugin_agent_connect schema with a fresh migration chain (the never-published auth 0015 is dropped). better-near-auth keeps only the wallet side: signAgentIntent signs a generated intent.payload with the connected wallet (nep413/nep366/webauthn); the BFF split means the browser never sees the naa_ key or ngt_ tokens. Drift kit: SDK catalog-pinned, an env-guarded live drift-gate test against the hosted /openapi.json, and the vendored near-intents-agent-api skill as the rules source. UI (agent accounts, budget view, grants) is a planned follow-up.
railway-app
Bot
temporarily deployed
to
heartfelt-ambition / everything-dev-pr-403
October 16, 2026 19:38
Destroyed
…t_id, honest idempotency, typed contract Review findings addressed: - submit and status polling now share one reconciliation path: a SUCCESS observed later applies the same local effects as an immediate one (grant id linked, revoke marked, agent row activated) - the intent ledger records the reserved agent_id at link time, so agent_create rows can activate on later success - idempotency made real: prepare routes accept an optional client idempotency key (8-128 chars); the stored response replays on reuse, an interrupted prepare resends the exact stored request body under the same key, and key reuse across intent types conflicts - contract outputs typed where the UI/helper need it (agent_id, signer, idempotencyKey, grant views) with passthrough elsewhere - the SDK stays the only shape authority No migration changes needed: the new plugin's unpublished 0000 chain was regenerated in place; the auth chain is untouched vs main.
…tion, idempotent prepare, type fidelity - stateful SDK mock (submit/poll status controls, generate-calls counter) - reconciliation tests: a SUCCESS observed by polling links the grant id and activates the agent row exactly like an immediate success (asserted against the store via the runtime's effect context) - idempotency tests: the same key replays the stored response without a second upstream generate; cross-type key reuse conflicts - type-level drift gate: the generated oRPC client returns the SDK's own response types, so signAgentIntent and the UI consume them without casts - contract outputs switched to z.custom<SDKType> (the SDK is the shape authority — zero re-declaration), README invariants + changeset updated
# Conflicts: # packages/better-near-auth/src/client.ts
The regression env guard refused to run: the new plugin's database secret was absent from the committed .env.test, so it resolved to the dev database (localhost:5432) and the stack preflight probed a port with nothing listening. Map it to the shared test api database, matching every other plugin *_DATABASE_URL and byte-for-byte what bos dev regenerates. Verified locally: regression HTTP dev (20/20) and start (20/20) green with the plugin booting in the stack.
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds the Agent Connect control plane as a dedicated plugin (
plugins/agent-connect): every signed-in user gets an owner-controlled agent account on the NEAR Intents Agent API — the owner signs the rules once with their wallet, and agents hold revocablengt_grant tokens that only act inside the owner-signed policy.Also lands:
docs/plans/target-state/README.md) — platform primitives inventory, the custody-first default path (decisions recorded 2026-10-16), the economy layer as open design space.agents/skills/near-intents-agent-api, lock-tracked) — the API's rules source for agent sessionssignAgentIntent(nep413 / nep366 / webauthn)main(custody publish, deploy-key mint,bos://import + source archives, consumer CI)Architecture
Separation of concerns — the domain moved out of the auth stack:
better-near-authclient (signAgentIntent)plugins/agent-connect(this PR)@near-intents-agent-api/sdk— the only protocol dependency (catalog-pinned); route outputs arez.custom<SDKType>so nothing can driftBFF split (per the API's canonical pattern):
agentCreate/prepareIntentreturnintent.payload+preview→ the browser signs →intentSubmitcarries the wallet's output. Thenaa_partner key andngt_grant tokens never reach a browser.Invariants (tested):
request+responsejsonb); link failure is fatal and retry-safeidempotencyKey— same key replays the stored intent or resends the stored request; cross-type reuse conflicts (upstream still enforces body equality)SUCCESSapplies the same local effects as an immediate oneSurfaces: the oRPC contract exposes the domain to REST and MCP via the host's OpenAPI mounts — agent operations are now agent-accessible, which Better Auth endpoints were not.
Migrations
plugins/auth: the branch-only0015_agent-connectwas dropped before merge (never published); the auth chain is identical tomain(…0014_deep_toad)plugins/agent-connect: fresh single-migration chain (0000_init), ownplugin_agent_connectschemaDrift kit
/openapi.json(AGENT_CONNECT_LIVE_CHECK=1)sdk-typescript,skills; privateapi,agent-connect)Configuration
Dormant until
NEAR_INTENTS_AGENT_API_KEY(naa_…) is configured. Secrets:AGENT_CONNECT_ENCRYPTION_KEY(vault key),AGENT_CONNECT_DATABASE_URL(pglite default for dev). VariableapiBaseUrlfor non-mainnet deployments.Testing
Follow-ups (deliberately not here)
bos logindefault path (vision doc graduation items)🚀 Squash-merge intended — the branch history carries pre-refactor lineages that the net diff supersedes.