Skip to content

Legal

Privacy

Last updated

Vestiarion is an autonomous treasury agent on Arc testnet. This page describes what the service stores and sends, as its code does it today. The code is public, so every statement here can be checked against it.

Signing in

You sign in with your email address: Supabase Auth emails you a one-time sign-in link, and there is no password. Where Google sign-in is turned on, you can use your Google account instead, and Supabase Auth receives your Google account's basic profile, including your email address. Your account is kept by Supabase Auth.

Signing in sets cookies that keep your session. When a sign-in link should take you somewhere other than the default page, such as an invitation, one more cookie remembers where, for up to an hour.

What a workspace stores

A workspace holds what its members and its agent put into it:

  • invoices, with their amounts, memos, purchase order references and due dates;
  • counterparties: their names, wallet addresses, screening results and payment limits, and their billing email when a member gives one, where payment notices and reminders go;
  • contractor milestones, with any GitHub pull request link used to verify one;
  • the agent's settings and its treasury records;
  • its members and their roles, and open invitations with the invited email addresses;
  • API keys and webhook endpoints;
  • the ledger: every decision the agent makes, with its reasoning, signed with Ed25519 and chained by hash.

It is stored in a Supabase Postgres database. Each request for a workspace's data runs as a database role that row-level security limits to that one workspace, so one workspace cannot read another's rows.

Who can see what

Only a workspace's members, and the API keys and webhook endpoints they set up, reach its data. Every member can see all of it; what a member can do depends on their role:

  • viewer: reads the workspace;
  • approver: also decides the payments the agent held, and pauses the agent;
  • admin: also adds records, runs and resumes the agent, and manages members, API keys and webhooks;
  • owner: also connects Circle, and can delete the workspace.

Nobody can approve an invoice they created. The service's own scheduled jobs, such as the agent's cycles and the cleanup below, work across workspaces.

The public open numbers page shows counts and totals across all workspaces, such as how many payments settled and how much USDC they moved. It never names a workspace or a person, and never lists a customer's payment.

An owner or admin can share one paid payment's receipt as a link. Anyone with the link sees that payment's amount, the payee's chain and address, its transactions and its signed ledger entry, which already sit on a public chain or in the workspace's own ledger. It shows no names. The link stops working when they stop sharing it or make a new one.

Secrets

The Circle API key and entity secret you connect, each webhook endpoint's signing secret, and each workspace's ledger signing key are encrypted with AES-256-GCM under the platform's master key before they are stored. Each is bound to its workspace and its field, so a copy moved into another row does not decrypt.

An API key is shown once, when it is created. Vestiarion keeps its prefix and a SHA-256 hash of its secret, never the secret itself.

Wallets and payments

Payments are USDC or EURC transfers on Arc testnet through Circle Developer-Controlled Wallets. A workspace that connects its own Circle account keeps its wallets in that account. A workspace that chooses hosted wallets has them created in Vestiarion's own Circle testnet account, so Vestiarion holds them; you fund them from Circle's faucet.

Payee history: anyone who pays for it over x402 can ask, for one Arc address, how many workspaces here have paid it with live payments, how many such payments were confirmed, and when the first and the last were made. The answer names no workspace and no amount. A workspace's agent can buy the same answer before its first payment to an address, from a service budget a person gives it.

Services that receive data

  • Vercel hosts the app.
  • Supabase holds the database and runs sign-in.
  • Circle creates the wallets and moves the payments, through Developer-Controlled Wallets, CCTP, Gateway and its Smart Contract Platform, so it receives wallet addresses and payment amounts. Its Stablecoin Service quotes EURC in USDC and builds the swaps of USDC for EURC, so it receives the operating wallet's address and the amounts. Gateway also verifies and settles the x402 payments for payee history, so it receives each signed payment: the paying wallet, the payee and the amount.
  • Resend sends transactional email: invitations to a workspace, digests of the payments waiting for a decision, the link a payee adds their address through, payment notices to a payee once a live workspace's payment to them is confirmed, and the reminders an owner or admin turns on for a client's invoice, with its pay link. It receives each recipient's email address and the message.
  • A model provider, when this deployment has one configured (Anthropic, OpenAI or DeepSeek), receives the context of each decision the agent asks it about, and nothing else:
    • for an invoice: its amount and currency, its value in USDC for an invoice in EURC, memo, purchase order reference, due date, early-payment discount and whether the goods were received, and, for one a recurring payment created, its period and how often it repeats; the counterparty's name, risk level, payment limit, whether it needs a purchase order and performance score, and, when the agent bought it before a first payment, how many workspaces here have paid its address, how often, and when first and last; the operating balance and the reserve balance, or for an invoice in EURC the wallet's EURC balance, its USDC balance and the USDC due within 7 days, and, when its EURC falls short, the swap of USDC for EURC that could fund it (the USDC it takes, the EURC it gives at least and as estimated, and what it costs above the quoted rate), or why there is none; how the payee is paid, on Arc or across chains through CCTP or a Gateway balance with its fee and expected time; the payment timing worked out from those: today's date and the due date, what the discount is worth and the last day it applies, the yield from keeping the cash to the due date, the day the written policy would pay on and the amount due that day, the total and number of payments that fall due on or before that day, and whether the cash available by that day falls short of covering this invoice after them; when the agent scheduled the invoice earlier, the date it chose and its reasoning; and any earlier invoices from the same counterparty that look like duplicates of it, each with its amount, due date and status, the signals that matched, how strong the match is and what the match found;
    • for a contractor milestone: its title, amount and verification source, how it was verified (whether, by what method, and the verifier's note), and the contractor's name, risk level, payment limit and performance score, and, when the agent bought it before a first payment, how many workspaces here have paid its address, how often, and when first and last;
    • for an invoice document a member chooses to read (a PDF, an email or pasted text): the document's text, up to 20,000 characters, to read its vendor, amounts, dates, terms and payment address into the invoice form. The document itself is not kept;
    • for a message a member sends the Telegram bot in plain words: the message, up to 4,000 characters, to tell which of the bot's questions it asks. The answer is read from the workspace and written by the app, not by the model;
    • for a reminder to a client: the receivable's amount and currency, its due date and how far today is from it, what it is for (its memo and purchase order), the client's name and how it paid its earlier receivables (on time, late, and how late on average), the reminders already sent (when, and how firmly), the tones allowed, and the written policy's answer. The email itself is a fixed text; nothing the model writes is sent to the client;
    • for a proposed payment limit: the counterparty's name, limit, risk level and performance score, and each payment people approved above that limit in the last 30 days (its amount, when, and what the agent had done with it), with how many were rejected;
    • for a treasury move: the operating and reserve balances, the reserve's yield, the obligations due in the next 7 and 14 days, the total open obligations and the days until the next one is due, and the sweep's economics worked out from those: the cash above the required buffer, how long it could stay swept, the projected yield and the cost of the transfers; the most a sweep may take, and the most and least a redemption may bring back; for 24 hours after a person brings cash back from the reserve, until when nothing is swept; and, for a real USYC reserve, that it is real and whether USYC can be bought now.
    A performance score comes with the counts it is computed from: payments paid without intervention, information requests, holds and flags, duplicate submissions, risk tier changes, and the holds the workspace's own limits caused. Without a model provider, a written rule-based policy decides, and nothing is sent.
  • Telegram, for a member who connects their own Telegram chat to a workspace, receives what the bot sends that chat: the workspace's name, the agent's decisions with the counterparties' names, the amounts, the reasons and links to the transactions and to the app, and the answers to the member's questions. It receives no email address or key, and no wallet address in full: one named in a reason or a warning is shortened to its first and last four characters. An invoice the member sends the bot reaches Telegram from the member, and the app reads it the way it reads one uploaded to the invoice form, without keeping it.
  • Slack, for a workspace an owner or admin connects to a Slack channel, receives what the app posts to that channel and its answers to members: the workspace's name, the agent's decisions with the counterparties' names, the amounts, the reasons and links to the transactions and to the app, who decided a payment from Slack, and the answers to a member's questions. It receives no email address or key, and no wallet address in full: one is shortened to its first and last four characters. The app reads no message in Slack but one an owner or admin chooses to add as an invoice, read the way one uploaded to the invoice form is, without keeping it. It keeps the Slack workspace's and the channel's ids and names, the app's token and the channel's posting address, encrypted, and the Slack user id of each member who connects their own account; disconnecting Slack deletes them, and the signed ledger keeps only the ids. A Slack username given to connect an account is kept until that request is used or expires, and cleared when the next one is made.
  • Resend, for a workspace that turns on invoices by email, receives the emails sent to its invoice address, as it receives every email at that domain. The app reads each one the way it reads an invoice uploaded to the invoice form and keeps the sender, the subject and what was read, with SPF, DKIM and DMARC as Resend reported them, until a person adds or dismisses it. The document itself is not kept, only its hash; the ledger keeps the sender's address with most of its name hidden.
  • OpenSanctions, when this deployment has it configured, receives the names and jurisdictions of a live workspace's counterparties to screen them. A sandbox, and any workspace on a deployment without it, checks names against a list built into the app and sends them nowhere.
  • GitHub is asked for a pull request's status when a milestone is verified by its link. For a workspace an owner or admin connects to GitHub, it also receives a comment on the pull request a milestone was paid for: the amount, the network, the workspace's name and the transaction's link, never the payee's name. The app keeps the installation's id, its account's login and type, and whether it covers all repositories or selected ones; disconnecting GitHub deletes them, and the signed ledger keeps only the ids and the login. The token of the person connecting, used once to check they can reach the installation, is not kept. GitHub also sends the app the comments on pull requests in those repositories. Only a comment with a line starting /bounty or /payto is acted on, and the rest are not kept. For each bounty, the app keeps the pull request, the logins of its author and of the person who attached it, the amount and the comment's link, and asks GitHub whether that person can write to the repository.
  • Google Analytics receives page views, as described below.
  • Product Hunt serves the badge on the home page, so your browser loads that image from Product Hunt, which sees your IP address and browser like any site an image comes from. Nothing else is sent to it.

Analytics

When this deployment sets a measurement ID, Vestiarion counts page views with Google Analytics 4. Before a page view leaves your browser:

  • an invitation address becomes /invite/:token, a payee link /payee/:token and a receipt link /receipt/:token, and a workspace address has the workspace's slug replaced, as /o/:org;
  • only the path is sent, never the query string or anything after a #;
  • the title of a workspace page, which names the workspace, is replaced with its redacted path;
  • a referrer on this site is redacted the same way, and a referrer from another site is cut to its origin.

Google signals and ad personalization signals are turned off. Google Analytics sets its own cookies to tell visits apart.

How long data is kept

  • A sandbox workspace with no activity for 60 days is deleted by a daily cleanup. A sandbox is kept if Circle credentials are connected to it, or if it holds a hosted wallet.
  • A webhook delivery is deleted 30 days after it is delivered; one that failed, 30 days after it was created.
  • Everything else in a workspace is kept until the workspace is deleted.

Deleting a workspace

An owner can delete a workspace from its Settings, typing its slug to confirm. A live workspace's agent has to be paused first, and deletion waits while a cycle is running or a payment is being made.

Deletion removes the workspace's invoices, counterparties, milestones, treasury records, ledger, API keys, webhooks, members and invitations, in one step, for everyone in it, and cannot be undone. Vestiarion keeps a tombstone that only the platform can read: the workspace's slug and name, who deleted it and when, and its ledger's length, head hash and signing key id.

The workspace's wallets stay in the Circle account that holds them, with any USDC in them. For hosted wallets, that is Vestiarion's testnet account.

Deleting your account

Delete account is in the menu under your email address, beside Sign out, and on the workspaces page. It needs no workspace role. Its dialog lists what will happen before anything does, and you type delete my account to confirm.

  • A workspace where you are the only member is deleted with your account, as an owner deletes one from Settings, so the same rules apply: a live workspace's agent has to be paused first, and deletion waits while a cycle is running or a payment is being made. Each leaves its tombstone.
  • If you are the last owner of a workspace that has other members, your account cannot be deleted until you make someone else an owner, or delete the workspace. Your teammates never lose a workspace because you left.
  • If you are the last owner of the founding workspace, your account cannot be deleted.
  • In a workspace with another owner, or where you are not an owner, only your membership goes.

If a workspace cannot be deleted, your account is not deleted. Otherwise your sign-in account is deleted, you are signed out, and your memberships and the invitations you sent go with it. API keys you created stop working. Records you added in workspaces you share stay, without your name on them. A workspace's signed ledger is append-only, so entries you caused keep your account's id (never your email). A workspace deleted with your account leaves its tombstone, and a tombstone keeps who deleted it, as your account's id.

Contact

Questions and requests go to GitHub Issues. The Terms of use cover using the service.