OpenRung
A free, privacy-first relay network that helps you reach the open internet. Open source and nonprofit-run.
翻訳待ち
Open source alpha for AI agents: verifiable EUDI Wallet mandates with scope, spending limits and expiry. Authorize agents without giving them full powers. On GitHub and npm.
翻訳待ち
セキュリティTypeScript · PLpgSQLGitHub @plenipo-net接続状況の再確認が必要です所有者未確認
Have you tried it? One tap is enough. No sign-in needed.
Mandates, not full powers: EUDI Wallet-anchored authorisation for AI agents
翻訳待ち
Loading the full README.
Read the full README ↗Mandates, not full powers. Plenipo lets a person authorise an AI agent from their European Digital Identity Wallet, and lets any service check that authority before the agent acts.
A plenipotentiary is an envoy who acts for someone and presents credentials to prove it. Plenipo gives AI agents the same thing, with one difference: the powers are never full. Every mandate has a scope, limits and an expiry, every sub-delegation can only narrow it, and the person can revoke it at any time.
Status: 0.5.1, experimental. The cryptography is real; wallets, PID providers and banks in the examples and the sandbox are test doubles. The code went through security reviews by independent AI review agents (two rounds for 0.3, two for 0.5), and their findings are fixed (see CHANGELOG.md); it has not yet been audited by an external security firm. Do not use it to protect real money or real data yet.
The EU Digital Identity (EUDI) Wallet is the state-recognised identity that every EU Member State must offer its citizens under eIDAS 2. It lets a person prove who they are online with the strength of an ID card at a counter, disclose only the data a service needs, and approve a specific piece of content, such as a payment, with that identity.
The wallet assumes the person is present. AI agents act when the person is not, and today they do it with passwords, API keys or saved cards: full powers, with no limits, no expiry, and no way for a service to know who authorised them. Plenipo lets a person approve a mandate in their EUDI Wallet once (allowed actions and counterparties, spending limits, expiry), lets the agent attach proof of that approval to every request, and lets any service verify it before acting. Sub-delegation can only narrow a mandate, and the person can revoke it at any time.
Person's EUDI Wallet Agent Sub-agent Service (MCP tool)
──────────────────── ───── ───────── ──────────────────
approves the mandate ──root──▶ holds mandate ──delegates──▶ narrower mandate
(PID + key binding over signs invocation ──▶ verifies chain,
the mandate hash) limits, revocation
ALLOW / DENY
urn:eudi:sca:emandate:1 type that certified EUDI wallets render, and let a
representative give a mandate on behalf of a company within the powers of their role.The wire formats and verification rules are specified in docs/spec.md, with test vectors for other implementations. The reasons behind them are in docs/design.md.
npm install plenipo
Node 22 or later. ES modules only.
From a clone of this repository:
npm ci
npm test # forged delegations, x5c, CRL/OCSP, status lists, OpenID4VP, TS12, shared stores, test vectors
# (Postgres and Redis tests run when the servers are available, and skip otherwise)
npm run demo # OpenID4VP approval, agent, sub-agent, a rail operator's MCP server
npm run example:gateway # a bank's HTTP API behind the Plenipo gateway
cd sandbox && docker compose up --build # a bank, a wallet, an agent platform and a live dashboard
The sandbox also runs with Node, has 17 scripted scenarios and an MCP bridge that lets Claude Desktop or Claude Code act as the agent. More in examples/.
The demo prints:
Booking bot: Roma-Milano 18 Oct, 89.00 euro
rail.example: ALLOW, acting for Mario Rossi, chain depth 1
Booking bot: Milano-Roma 20 Oct, first class, 120.00 euro
rail.example: DENY LIMIT_PER_OPERATION, amount 12000 exceeds 10000 on mandate 1
...
The person revokes the mandate; the platform flips its entry in the status list.
rail.example: DENY REVOKED, mandate 0 is revoked in its status list
This is the beginning of the README. Read the rest at the original. Read the full README ↗