feat: let signed-in visitors lend NPCs their own CORE integrations#72
Open
omjeem wants to merge 4 commits into
Open
feat: let signed-in visitors lend NPCs their own CORE integrations#72omjeem wants to merge 4 commits into
omjeem wants to merge 4 commits into
Conversation
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
Today an NPC can only use the integrations the town owner wired into its mdx (
permissions.integrations), acting on the owner's connected accounts.This PR lets a signed-in visitor lend an NPC their own CORE integrations for a conversation, so the NPC can act on the visitor's account (e.g. read the visitor's own Postman workspace) instead of the owner's — without the owner ever
seeing the visitor's credentials. The visitor stays in control: they grant from an in-chat popover and can revoke from the same place anytime.
How it works
VisitorIntegrationGranttable (npc × visitor × slug), soft-deleted viarevokedAtso grant history stays auditable and re-granting is an upsert. Pure DB helpers live invisitor-grants.ts.buildNpcToolsnow builds up to two integration sources (owner + visitor) and routes eachexecute_integration_actionto the correct token byintegration_account_id(globally unique in CORE). One NPC can acton the owner's and the visitor's accounts in the same conversation. Memory, tasks and skills always stay on the owner token — only integrations route to the visitor.
resolveViewernow returnsuserId(null for anonymous guests). The owner is treated as a non-granter:visitor-accessreturnsisOwnerand the server rejects owner writes, so the feature is enforced at both the UI and API layers.sourcestring (town:npc:<id>:resident|visitor) so CORE's call log can attribute which NPC, and whose account, made the call.Testing
Migration:
pnpm db:migrate(ordb:deploy) applies20260720000000_visitor_integration_grant.Limitations / scope (v1)
actions[]column for a future per-tool (level-2) whitelist — it can land later without a migration.town deploy. Deploy recreates NPC rows (delete + recreate), which cascades the grants away. Acceptable for now; a later change can switch deploy to upsert-by-id to preserve them.resident/you) and it's told to prefer the visitor's own. This is a prompt-level preference; enforcement is the token routing.Follow-ups (not in this PR)
belongs_to: "you"accounts is a good next step.visitor-integration-grants.mp4
Closes #48.