Security

We cannot lose your key.
We never had it.

I have been building websites since 1995 and I have read a lot of security pages. Most are a list of promises. This one is a list of things you can check.

We hold as little as we can. Your key is made on your device and never reaches us. The key that signs you in is not the key that holds your money. An agent’s limit is the most it can ever cost you. None of that is policy. It is how the thing is built.

Where we accept a risk, the table says so in the same row as the defence. Where something is still being built, this page says built, and never shipped.

Disclosure address security@one.ie · machine-readable at /.well-known/security.txt

How it works

In plain words

Seven steps, in the words we would use at the kitchen table. Every one of them is true of the code as it runs today.

  1. A key is born on your device.

    You touch the sensor. Your browser makes thirty-two random bytes. That is your key. Nobody else was in the room, so nobody else has a copy.

  2. The key makes your addresses.

    From that one key we work out your addresses on Sui, Ethereum, Solana and Bitcoin. Same key, same addresses, every time, on any device.

  3. You keep it three ways. You choose.

    Your fingerprint locks a copy on the device. Your twenty-four words on paper are the key itself. Or an encrypted file in a folder you pick. Any one of the three brings everything back.

  4. To spend, the key opens for one act and closes.

    You touch the sensor. The key unlocks, signs one thing, and is wiped from memory. It is never sitting open, waiting to be stolen.

  5. Signing in and spending use different keys.

    The key that logs you in holds nothing. The key that holds your money never logs in. Phish a login and you get a door, not a vault.

  6. Agents get their own small keys.

    An agent you hire gets a child key with a ceiling you set. It can spend up to the ceiling, never past it, and you can take it back any time.

  7. We hold only locked boxes.

    If you choose to keep a copy with us, we hold ciphertext that only your fingerprint opens. We cannot read it. Neither can anyone who breaks in.

That is the whole thing. A key nobody gave you and nobody can take. The twenty-four words open in any wallet on earth, so you can leave with everything, and that is exactly why it is safe to stay. We think this is the only kind of security worth building, so we are giving it away.

Three facts

Not three promises

Each one is a property of the code, not of our good intentions. Each links to the page where you can read how it works.

Your key is born on your device.

Touch the sensor. Thirty-two random bytes come into existence in your browser and become four addresses, one per chain. The secret behind them never leaves the machine in your hand. We cannot hand it over, freeze it or lose it. We cannot get it back for you either. The twenty-four words on paper are the key, not a hint at it.

See how the key works Recover a key from its words

The key that signs you in holds nothing.

Sign-in is done by a child key, bound once to the account that holds the money. Every login after that is signed by the child alone. Phish a login and you get the door, not the vault. The challenge you sign is spent before a session issues, so a signature seen once is worth nothing the second time.

Read the wallet docs

An agent’s ceiling is the most it can cost you.

A person and an agent can share money four ways. You co-sign each act. The agent works inside a limit. You mint one bounded capability and the agent spends it. Or the agent is a peer with full authority inside its scope. The default is co-sign. Leaving it is a decision you make, never a setting that drifts.

See what agents can do

The inventory

What we hold, and what we never will

A break-in is only as bad as what was there to take. This is what is there.

We never hold

  • Your master key, or the twenty-four words. They are the same thing
  • The passkey output that wraps the key. It is zeroed the instant the wrap is written
  • A password. There are none. Nothing to reset, nothing to phish
  • A plaintext API key. We keep a hash and compare

We do hold

  • A hash of each API key. A leaked database gives up nothing that opens a door
  • An encrypted copy of your key, only if you chose to keep one with us, that only your fingerprint opens. We hold the ciphertext and cannot read it
  • Your workspace. The people, agents, tasks, wallets and messages inside it
  • A record of what happened. That record is the audit trail, and it is what an attacker who reached the database would be reading
  • The key to an escrow address, for the minutes a crypto payment is in flight. We do not store it — we can re-derive it, which is the same power. It is the one place we hold spend authority, and it is on purpose

The threat model, as a table

What it defends, and what it accepts

Every line on the left is paid for by the line on its right. A security page with only a left column is hiding the right one.

Defends A crypto payment that arrives while nobody is watching. The escrow address is ours to sweep, so the money reaches the seller without the buyer waiting on us or the seller trusting a stranger

Accepts For those minutes we can move it. A break-in deep enough to reach the escrow seed could sweep every escrow in flight. Nothing in flight is insured, and a payment straight to a seller address never touches this rail at all

Defends A break-in on our servers. The keys are hashes, the wraps are ciphertext, and the master never came here

Accepts Your account rows and your history are readable to whoever got in. They are the audit trail, not the vault

Defends A phished password. There is no password to give away, and a passkey answers only to the site it was made on

Accepts A real sign-in challenge can be shown to you on a page that is not ours. A bound wallet gives up the door. A wallet that never bound a child key signs with the key that holds, and gives up more

Defends A phished payment. The transaction is shown to you in plain words before the sensor is touched. Nothing hides what you are authorising

Accepts Cryptography does not fix social engineering. A person can approve a transfer that looks legitimate and is not, and there is no clawing it back

Defends A lost phone. The twenty-four words bring the same addresses back on any device

Accepts Lose the paper and every device and the money is gone. No reset, no support line, no back door. That is the price of nobody being able to take it from you

Defends An agent that misbehaves. Its ceiling is the most it can cost, and the model never holds a signing key. It can propose. The limit decides

Accepts Inside its scope an agent can do things you did not anticipate. The scope is yours to set narrow

Defends A stranger calling our API with an invented token. The token decides nothing. The label on each door does, and a door that needs a member refuses a caller who is not one

Accepts A door with no label is open today. We publish which gate binds and which does not. Labelling every door is on the list below

Defends A model that is lied to. Prompt injection reaches a model that holds no key and no authority of its own. Its output is checked before anything moves

Accepts Injection that stays inside the tools an agent was given, and does something unhelpful with them, is not caught by a key it never had

Defends Our own infrastructure. We run on Cloudflare’s edge and keep the brain in TypeDB Cloud. Neither holds anything that opens your wallet

Accepts We do not own the metal. A stack on your own servers beats us on physical control, and we will say so to your face

Defends Nothing, in one case. Someone who has physical control of you and your device at the same time

Accepts Out of scope. We do not defend against coercion and we do not pretend to

Verification over presence

What we check, not what we assert

A file existing is not a control. A control is something that can come back red.

Our disclosure file cannot go stale.

RFC 9116 says a security.txt with a past expiry is invalid. Ours computes its expiry on every request, so it cannot rot.

Read security.txt

We measured the perimeter and published the numbers.

The API docs carry the probes we ran against production, including the one where a sixteen-character junk token walked through the first gate. The docs say which gate binds and which is a doormat.

Read the two gates

Saved means read back.

We do not call a key kept until the stored copy has been read back from disk and checked against the one in memory. A passkey being created and a key being stored are two different facts, and the code treats them as two.

A check that did not run did not pass.

Every gate in our build answers pass, fail or unrun, and unrun is never a pass. Any number this page quotes is one the tests compute, which is why this page carries no counts.

Your data

Erasure is a call, not a ticket

One request to POST /api/forget starts a cascade across everything tied to an identity and answers with a receipt. You poll it and watch it complete tier by tier. A subject access door returns the full record we hold, so you can read it before you decide.

We hold no SOC 2 report and we will not print one we do not have. We built it so that when an auditor arrives there is little to audit. No passwords. No plaintext keys. No master that ever left your device.

Erase
POST /api/forget → cascade receipt, pollable
Access
POST /api/ask/compliance/dsar → the full subject record
Where
Cloudflare edge for the request path · TypeDB Cloud for the brain
Certifications
None held. None claimed.

Still being built

What this page does not get to say yet

Each of these moves up into the tables above when it ships, and not a day before.

  1. A label on every door.

    Each API receiver declares who may call it. Some declare nothing, and an undeclared door is open. Two parts to the fix: label them, and add a test that refuses to ship a new one without a label.

  2. Locks on the page itself.

    A key is only as safe as the page around it. Today one.ie sends no Content-Security-Policy header, so a script that got onto the page could read a key that has not been sealed yet. The fix is a strict policy on the key pages first, then the rest of the site.

  3. An honest answer to a stranger.

    An unauthenticated call currently gets a refusal that teaches nothing. It will get the map instead: where the catalog is, how to mint a key in one call, how to sign in with a wallet.

  4. Our name on the sign-in challenge.

    The statement a wallet signs will name our origin, so a copied challenge shown on another site reads wrong in the wallet before anyone signs it.

  5. Ceilings enforced on-chain.

    Agent spending limits that consensus enforces rather than our code. Designed. Co-sign is what ships today, and this page will say shipped when it is.

Found something?

Tell us what you measured. We answer with what we measured.

Write to security@one.ie with the request you sent and the response you got. A probe against production is welcome when it reads and does not write.