# send.sgit.ai
> Send a file to anyone, encrypted in your browser before it leaves. The server never sees the file, its name or the key. Hand over the link as a QR code, or keep the files in a vault you can open again, update, and clone with sgit.
Site version: v0.1.2 (2026-10-20). send.sgit.ai is the product site: the app (send, open, vaults, keys), the explanations, the examples and the commercial model. The code it runs is api.send.sgit.ai v0.1.1, pinned in tools/api.json. Source: https://github.com/SGit-AI/SGit-AI__Website__Send
Every HTML page has a markdown twin at the same path with the extension swapped; links inside the markdown point at pages. If your tooling cannot follow links, fetch /llms-full.txt: every page in one request.
## Pages
- [send.sgit.ai, send a file, keep the key](/index.md): Send a file to anyone, encrypted in your browser before it leaves. The server never sees the file, its name or the key. Hand over the link as a QR code, or keep the files in a vault you can open again, update, and clone with sgit.
- [About this site](/about/index.md): What send.sgit.ai is, how it is run, what it carries as every repository in the estate does, and where each of those things is.
- [The brief, in full](/about/brief/index.md): The four voice memos of 20 October 2026 that started this site and api.send.sgit.ai, published as spoken, with the status of each and what was done from it.
- [Brief corrections](/about/corrections/index.md): Where the brief was wrong, where the agent's reading of it was wrong, and what was done instead; the brief itself is never edited.
- [What needs a human](/about/needs/index.md): The steps only the project lead can take for this site to be live and for the proposed rows to move, in order, with what each unblocks.
- [Participant disclosure](/about/participant/index.md): Who publishes this site, what they are building, and why that matters when reading its claims.
- [Reality, what exists](/about/reality/index.md): The code-verified list of what this site implements, generated from website/data/features.json on every build. If it is not listed here, it does not exist.
- [The team](/about/team/index.md): Who does what on this repository, as files: one person, one build agent, and the roles borrowed from the SG/Send team when their expertise is needed.
- [Articles](/articles/index.md): This site's own articles: the person's voice memos written up on this site's dimension, and the agents writing what they delivered, in the newsroom's format so they can be imported unchanged.
- [Every site its own articles: the guidance, in one place, for the agents that write what they delivered and the memos that become articles](/articles/every-site-its-own-articles.md): A lot of the websites we now create need their own articles, because the pattern I am using works. It has two halves. Agents write, in detail, what they just delivered, with the commits and the tests to check it against. And my voice memos become articles too, each one focused on the particular dimension that site is about, whether that is sgit, PKI, the Gen Z book, or Send. It started on sgit.ai, moved to the newsroom, and now it is on most of the sites, which means I find myself telling the same story over and over to each agent doing it. This is the centralised page I can point them at instead: what an articles section on a site is, the two kinds of author and how each is marked, the shape of an article so it can be imported into the newsroom unchanged, the rules that were each a correction once, and the prompt that starts one. It is written as a brief, so the newsroom can publish it and sgit.ai's guidance can import it, and so the next site gets it for free.
- [Send moves to sgit.ai: the keys were the missing piece, and now they are not](/articles/send-moves-to-sgit.md): This is the brief for refactoring SG/Send, the file transfer service at send.sgraph.ai, into send.sgit.ai, and it is a good example of how innovation gets stuck when the infrastructure underneath it is a little hard to maintain and move. I have a great set of automation and capabilities there, and the innovation on it fell off a cliff. The market told me things were missing, and what was missing was fundamentally what we have now solved: the keys. Where do the vault keys live, and where does a user keep the access key that lets them push? Because there was no answer, everything ground to a halt, with quite a decent number of customers who then did not get to use it. So the time has come to move it to sgit.ai, also because SGraph, "secure graph", was always a strange brand. What I have in mind is send.sgit.ai: still the send thing, data from A to B, but with the vault keys stored and the files kept in vaults, which changes the whole sharing experience; QR codes embraced as the way to hand a link over; and the code kept separate at api.send.sgit.ai, versioned and released, so the site is the usage and the examples and the commercial model, and the capability can be embedded anywhere else.
- [What shipped in v0.1.0: five pages, one pinned release, one browser test that sends, opens and shares](/articles/what-shipped-in-v0-1-0.md): I am the agent that built send.sgit.ai v0.1.0 on 20 October 2026, in the same session as api.send.sgit.ai v0.1.0, from four voice memos Dinis Cruz recorded that morning. This is what I delivered, with the files and the test to check it against. The site is five app pages and sixteen content pages. The app pages import one pinned release of the API by its full address, with the release's manifest copied beside the pin and a gate check that refuses any other reference. Send takes a file, encrypts it in the browser with its name inside the ciphertext, and uploads it as a transfer or commits it into a vault; it hands over a link with the key, a friendly token, or a link with the key shown separately, and draws every one as a QR code. Open takes any of those forms, or a vault's read key, and decrypts here. Vaults creates, opens, adds to, publishes with compare-and-swap, and shares read-only. Keys is the keyring on the device. Settings chooses the server and keeps the access token. One Playwright test drives all of it in Chromium against the pinned release and the API in memory. The content pages, the brief in full, the corrections, the reality file and the commercial model say what is not there yet.
- [Keys](/keys/index.md): The keyring on this device: vault keys, read keys, the transfers you sent and their delete secrets, and access tokens. Plaintext in this browser's storage, exportable to a password manager, never uploaded.
- [How it works](/learn/index.md): What happens to a file between the drop zone and the recipient, step by step, with what each party holds at every step.
- [From send.sgraph.ai to here](/learn/from-sgraph/index.md): What send.sgraph.ai did, what stopped it, what this site keeps, what it adds, and what it does not carry yet.
- [QR codes and friendly tokens](/learn/qr-codes/index.md): Why the link is drawn as a QR code, what the code carries and does not, and the trade a friendly token makes against a random key.
- [Security, what the server sees](/learn/security/index.md): What the server can see, what it cannot, the two secrets that must not be confused, what a friendly token costs, and what this site does not claim.
- [Vaults and keys](/learn/vaults-and-keys/index.md): What a vault is, the one secret and the keys derived from it, which may be shared and which never, where each kind of key should live, and what to do when one is lost.
- [Open a link](/open/index.md): Open a transfer link, a friendly token, or a vault's read key. Everything after the # stays in your browser; decryption happens here, and opening needs no account and no token.
- [Settings](/settings/index.md): Which SG/Send server this browser talks to, the access token for it, and which copy of the API the pages load. All of it stays in this browser.
- [Examples, a page, curl, Python](/use/index.md): The same transfer made three ways: from a page with the pinned API, from a shell with curl and openssl, and from Python for an agent; plus the server in memory for trying it on a laptop.
- [For agents](/use/agents/index.md): How an agent sends a result to a person or to another agent with these formats, what to put in the bundle, which secrets go where, and the pages to read first.
- [Embed it in your site](/use/embed/index.md): Put a send box, an open page, or a QR hand-over on your own site by pinning the same release this site runs; what to pin, what to check, what stays on your origin.
- [The commercial model](/use/pricing/index.md): How using this site and its capabilities is meant to be paid for, what is true today (a beta behind access tokens), what is proposed, and what will never be charged for.
- [Vaults](/vaults/index.md): The vaults this browser holds keys for. Create one, add files as commits, see the history, and share it read-only with a link and a QR code; clone it anywhere with sgit.
- [Version history](/versions/index.md): One line per version, newest first, saying what changed and why. Every change that lands on dev is a version; the deploy tags it.
- [The API this site runs, for agents](https://api.send.sgit.ai/agents/index.md)
- [The pinned release's README](https://api.send.sgit.ai/v0.1.1/README.md)
# send.sgit.ai, send a file, keep the key
> Send a file to anyone, encrypted in your browser before it leaves. The server never sees the file, its name or the key. Hand over the link as a QR code, or keep the files in a vault you can open again, update, and clone with sgit.
*Source: · send.sgit.ai v0.1.2 · this file is generated from the same content as the page, so the two cannot drift. Every page on this site has a `.md` twin; internal links below point at pages, swap `.html` for `.md` to read the twin.*
---
# Send a file. Keep the key.
The file is encrypted here, in your browser, with its name inside the ciphertext. The server gets bytes it cannot read. You get a link, a QR code, or a token you can say aloud; whoever has it gets the file, and nobody else does, the server included.
**Beta:** uploading needs an access token. [Set one in Settings](/settings/), or [read how to get one](/use/pricing/). Opening a link needs nothing.
Drop a file here, or click to choose
Encrypted in this browser before upload · under 4 MB for a one-off transfer · any size into a vault
Several files go into a vault, as one commit.
Where it lives
One transfer: uploaded once, handed over once, expires
Into a vault: versioned, updatable, clonable with sgit
Expires
in 1 dayin 7 daysin 30 daysnever
Downloads
unlimitedoncefive times
Which vault
Name for the new vault
How to hand it over
A link with the key in it (and a QR code)
A friendly token you can say aloud, river-cloud-3847
A link, with the key sent separately
For a vault the link carries the read key; the vault key stays on this device.
Encrypt and send to the server set in [Settings](/settings/)
## What happens, in one table
StepWhereWhat the server gets
The name goes inside an envelope in front of the filethis browsernothing
The whole thing is encrypted with AES-256-GCM under a fresh keythis browsernothing
The ciphertext is uploaded as one transfer, or committed into a vaultthe server you choseciphertext, its size, a hashed sender IP, a content type hint you choose
The link is built with the key after the `#`this browsernothing: browsers never send the fragment
The link is drawn as a QR codethis browsernothing
[How it works](/learn/) · [What the server sees](/learn/security/) · [Vaults and keys](/learn/vaults-and-keys/) · the code this page runs is [api.send.sgit.ai v0.1.1](https://api.send.sgit.ai/v0.1.1/README.md), pinned.
==============================================================================
# About this site
> What send.sgit.ai is, how it is run, what it carries as every repository in the estate does, and where each of those things is.
*Source: · send.sgit.ai v0.1.2 · this file is generated from the same content as the page, so the two cannot drift. Every page on this site has a `.md` twin; internal links below point at pages, swap `.html` for `.md` to read the twin.*
---
# About this site
send.sgit.ai is the product site for sending files with the key kept by the people, not the server: the app ([send](/), [open](/open/), [vaults](/vaults/), [keys](/keys/), [settings](/settings/)), the explanations, the examples, the commercial model and the articles. The code it runs is [api.send.sgit.ai](https://api.send.sgit.ai), pinned. The repository is [SGit-AI__Website__Send](https://github.com/SGit-AI/SGit-AI__Website__Send); it grew from [send.sgraph.ai](https://send.sgraph.ai), and [from send.sgraph.ai to here](/learn/from-sgraph/) says what changed.
It follows [what every sgit repository carries](https://sgit.ai/docs/guidance/repositories.html):
| Thing | Where |
|---|---|
| The brief, in full | [/about/brief/](/about/brief/), from `briefs/` |
| The reality file | [/about/reality/](/about/reality/), from `website/data/features.json` |
| The corrections file | [/about/corrections/](/about/corrections/), `BRIEF-CORRECTIONS.md` |
| One version, going up on every push | `tools/version.json`, in every header, [the history](/versions/) |
| The gate | `tools/check.py`: the build is committed, links, twins, origins, the API pin, the tripwire, prose, the version |
| Tests against real things | `tests/test_app.mjs`: the pages in Chromium against the pinned release and the API in memory |
| The review folder | `review/intent/`: the brief as sections; the derived graph is proposed |
| Roles and a board, as files | [/about/team/](/about/team/), `team/` |
| A credentials tier that is never committed | nothing in this repository needs a credential; the tripwire scans every tracked file anyway |
| Machine-readable twins | a `.md` beside every page, [/llms.txt](/llms.txt), [/llms-full.txt](/llms-full.txt) |
| Licences and the disclosure | code Apache-2.0, content CC BY 4.0, [the participant disclosure](/about/participant/) |
What only a person can do next is on [/about/needs/](/about/needs/).
==============================================================================
# The brief, in full
> The four voice memos of 20 October 2026 that started this site and api.send.sgit.ai, published as spoken, with the status of each and what was done from it.
*Source: · send.sgit.ai v0.1.2 · this file is generated from the same content as the page, so the two cannot drift. Every page on this site has a `.md` twin; internal links below point at pages, swap `.html` for `.md` to read the twin.*
---
# The brief, in full
A repository here starts from a brief published in full, written by a person or by an agent from the person's words, and never edited afterwards to look right; corrections go in [the corrections file](/about/corrections/). These are the four voice memos Dinis Cruz recorded on 20 October 2026 and handed to the agent in one session, as transcribed. The reading of them that the agent worked from is at the end; where that reading was wrong, the corrections file says so.
**Status:** accepted, 20 October 2026, by being handed to the session with "let's build this". **What was built from them:** this site and [api.send.sgit.ai](https://api.send.sgit.ai), both at v0.1.1; [the reality file](/about/reality/) says which parts exist.
## Memo 01: Refactoring SG/Send to sgit.ai {#memo-01}
*Voice memo by Dinis Cruz, 20 October 2026, transcribed by otter.ai; the file is `briefs/2026-10-20__01__refactoring-sg-send-to-sgit-ai__transcript.txt`. Published as spoken, with the transcription's own spellings of product names left in: "SG Sans", "Skit", "esquito AI" are sgit.ai; "S Graph", "SGCN" are SGraph; "IFT"/"AFD" are IFD.*
> Dinis Cruz 0:00
> Okay, so this is now a brief for the refactoring of the code and the services that we have on SG Sans. Basically, the file transfer services, which actually is a good example of when you write an article of how innovation gets stuck when you have infrastructure that is a little bit hard to maintain and move. So even though I have a really great set of automation, I have a really great set of capabilities. The if you look at the innovation on the sand, it has like fall off a cliff, right? And yes, you know I got valuation on the market that there was stuff missing, and to be honest, the stuff that was missing was fundamentally what we now solved, which is the keys, right? Is basically storing the keys, storing the vault keys, storing the even the you know the biggest biggest attrition we had there was where do the users store the access key to be able to commit and push files, right? So because because we didn't have that, then everything grounded to a halt, right? And we had actually quite decent amount of customers, that then, you know, it didn't actually work. So I think the time has come to move that to Skit, also because SGCN was also S Graph was also a weird brand, right? Secure Graph doesn't really work. So, so what you now have is fundamentally I want to do send.skit.ai because it's still the send stuff. Are you sending data from B to B? And also now we also have agentic workflows that need that, and we're about to have PKI all wired in, so there's a massive intersection of this. So the point is to now have a new website that replicates the functionality that we had on the on send. Graph. AI, but now with the ability to store the vault keys and store the files in vaults, which makes a massive difference. So from a sharing point of view, the whole experience is much better, and also we we should embrace QR codes, which I think is a much better way of doing everything instead of those pass keys, and then we'll we'll take it from there.
## Memo 02: The API and the commercialisation strategy {#memo-02}
*Voice memo by Dinis Cruz, 20 October 2026, transcribed by otter.ai; the file is `briefs/2026-10-20__02__api-and-commercialisation-strategy__transcript.txt`. Published as spoken, with the transcription's own spellings of product names left in: "SG Sans", "Skit", "esquito AI" are sgit.ai; "S Graph", "SGCN" are SGraph; "IFT"/"AFD" are IFD.*
> Dinis Cruz 0:02
> This is also for the agent who's working on the same dot escrito AI, and the logic is to also have, as we just you know mentioned before, but basically the logic is to have an api.send.skit.ai, which is the one that we go into version control that we're going to release that we're going to basically map everything out from, and that's fundamentally the code that then the send uses, but also will help to embed will help to embed the will help to embed the functionality in other places, right? And I think that's quite powerful, and also it keeps the code nicely separated. We have nice releases, and we maintain it. So then, then the main sand website becomes fundamentally the usage of it, and and they can basically the examples, and also the commercialization angle of it, right? Because remember that the whole point of this is for this to have the full-blown usage commercial model of of using the site and using the the capabilities of the site. So yeah, so let's build this.
## Memo 03: API development and the versioning strategy {#memo-03}
*Voice memo by Dinis Cruz, 20 October 2026, transcribed by otter.ai; the file is `briefs/2026-10-20__03__api-development-and-versioning-strategy__transcript.txt`. Published as spoken, with the transcription's own spellings of product names left in: "SG Sans", "Skit", "esquito AI" are sgit.ai; "S Graph", "SGCN" are SGraph; "IFT"/"AFD" are IFD.*
> Dinis Cruz 0:00
> So one of the things that we should be publishing here is an article about a pattern that is starting to emerge, which is the pattern of creating APIs for some of these websites, and the logic is leveraging a lot of the ideas that I published in the past for the iterative flow development (IFD) which you can find quite a bit online, the logic is to have a domain. So let's say storyboards, which is a website coming soon. So you have storyboards.ski.ai, and basically what we are going to do with that is we're going to have the API dot storyboard esquito AI same way that we have the API dot newsroom AI the same way that we're going to have API dot send dot esquito AI and and basically the logic is to start to have these releases which fundamentally should be all version controlled using the AFD, but the difference here is a little because now actually the models are better and it works a lot more smoother. Now the idea is that every minor release is 100% independent, so every minor release is actually a full copy of all the code, right? And unless for some reason we actually want to use the previous one, but in principle for these ones, because we're keeping the scope quite limited, and because it's an API, remember, we it should be all independent, right? And then we do the whole quality control, the quality releases, and then every release is a minor, you know, and then on the major one, we we basically again do the refactoring into that version. So I guess the main difference from the IFT is the fact that now we we don't have the overwrite, which is actually not as needed in this particular case because in a way what eventual happens we'll have a fractal element of this. So each one component should be independent by itself
## Memo 04: Centralised article briefing guidance {#memo-04}
*Voice memo by Dinis Cruz, 20 October 2026, transcribed by otter.ai; the file is `briefs/2026-10-20__04__centralised-article-briefing-guidance__transcript.txt`. Published as spoken, with the transcription's own spellings of product names left in: "SG Sans", "Skit", "esquito AI" are sgit.ai; "S Graph", "SGCN" are SGraph; "IFT"/"AFD" are IFD.*
> Dinis Cruz 0:00
> One of the article briefs that we need to create is the the now the the mode that we're having where a lot of websites are now that we create now need to have their own articles because because the agents now like the pattern that I'm using here it's actually very effective where not only we have agents writing detail what they just delivered. We also have articles that are created for my voice memos, which are again specifically focused on that particular what's it called on that particular dimension. You know where. the skit or PKI or or the Gen Z book, you know, and actually, if you think about, you started with the skit and I moved to newsroom, the skit. So I think we just need a centralised place where we have guidance for the. So at the moment, I'm finding myself telling the same story over and over again to the multiple agents that are doing this, and I just need that centralised. I need that centralised page or article for now that I can point to it. As in fact, this should be part of the guidance also of the main Eskito AI website. So again, we can put this person in a newsroom, and then we can import that again. Is a brief to create that page, right?
## The agent's reading of the four memos {#reading}
1. **Move SG/Send to sgit.ai** as `send.sgit.ai`: the same job (send data from A to B, encrypted in the browser, the server never sees a key) with the two things that were missing and are now solved, somewhere to keep the vault keys and files kept in vaults rather than one-shot transfers, and QR codes as the first way to hand a link over.
2. **Split the code from the site**: `api.send.sgit.ai` is the versioned, released, embeddable code that `send.sgit.ai` uses and that other places can embed; the site is the usage, the examples and the commercial model.
3. **Version it as independent releases**: every minor release is a complete copy of the code, no overlays, each quality-controlled; refactoring happens at the major. An article on this pattern, which the newsroom's API already follows.
4. **A centralised guidance page on every site carrying its own `/articles/`**: agents writing what they delivered, and articles written from voice memos on that site's own dimension; one page to point every agent at, published where sgit.ai can import it.
==============================================================================
# Brief corrections
> Where the brief was wrong, where the agent's reading of it was wrong, and what was done instead; the brief itself is never edited.
*Source: · send.sgit.ai v0.1.2 · this file is generated from the same content as the page, so the two cannot drift. Every page on this site has a `.md` twin; internal links below point at pages, swap `.html` for `.md` to read the twin.*
---
# Brief corrections
The brief ([published in full](/about/brief/)) is never edited to look right afterwards. This page is the file `BRIEF-CORRECTIONS.md` in the repository, rendered: where the brief was wrong, where the agent's reading was wrong, what was found and what was done instead, dated, with the mistake left visible.
| Date | Where | What was found | What was done |
|---|---|---|---|
| 2026-10-20 | Memo 1, "replicates the functionality that we had on send.sgraph.ai" | send.sgraph.ai at v0.34 has far more than a first release can carry: folders, text and secret transfers, presigned multipart uploads, seventeen locales, a share zip of a vault, a gallery, an admin console. | v0.1.1 carries the core: transfers under 4 MB, friendly tokens, QR codes, vaults with the keyring. The rest is listed as proposed in the reality file and on /learn/from-sgraph/, never described as present. |
| 2026-10-20 | Memo 1, "embrace QR codes, which is a much better way instead of those pass keys" | "Pass keys" most likely means the friendly tokens and the beta access gate, not WebAuthn passkeys; the transcription does not settle it. | QR codes carry the link, with the key or the friendly token, and are drawn on every share. Friendly tokens stay as the spoken form. WebAuthn passkeys are untouched and belong to secrets.sgit.ai. |
| 2026-10-20 | Memo 2, "the full-blown usage commercial model" | No billing, no self-service tokens and no meter exist on the server or on this site; access tokens are issued by hand. | /use/pricing/ states what is true today (free to open, a hand-issued token to send) and lists the model as proposed, row by row. |
| 2026-10-20 | Memo 4 | The memo asks for the centralised guidance page to be published in the newsroom and imported from there. This session has write access to the two Send repositories only. | The page is /articles/every-site-its-own-articles.html here, in the newsroom's article format so it imports unchanged; moving it is on /about/needs/. |
| 2026-10-20 | The app, interoperability | A link made here opening on send.sgraph.ai is asserted from the shared formats and the tests against the in-memory server, not from a run against the hosted site. | Marked proposed in the reality file until a round trip is recorded; the test to run exists in the API repository. |
| 2026-10-20 | The keyring | The brief asks for "the ability to store the vault keys"; a plaintext localStorage keyring stores them but does not protect them. | Built as the first version, with the limit written on the Keys page and the stronger homes named; the passkey-unlocked keyring stays proposed. |
==============================================================================
# What needs a human
> The steps only the project lead can take for this site to be live and for the proposed rows to move, in order, with what each unblocks.
*Source: · send.sgit.ai v0.1.2 · this file is generated from the same content as the page, so the two cannot drift. Every page on this site has a `.md` twin; internal links below point at pages, swap `.html` for `.md` to read the twin.*
---
# What needs a human
1. **Merge the branch to `dev`** in both repositories. The deploy workflow runs on `dev`; the branch `claude/wonderful-ride-c8qicn` carries v0.1.1 of both. Then keep `ref` in `tests/api.json` at `dev`, so the browser test checks out the merged API.
2. **api.send.sgit.ai first:** done. The host is live and this site loads its code from it; the live check after each deploy confirms it.
3. **Enable GitHub Pages for this repository** with the source set to GitHub Actions, and a `CNAME` record for `send.sgit.ai` pointing at `sgit-ai.github.io`.
4. **CORS on the hosted server:** done. Measured on 20 October 2026 after the first deploy: `send.sgraph.ai` allows requests from this origin with every header the release sends.
5. **A round trip against the hosted server** with an access token, to move interoperability from proposed to shipped in both reality files.
6. **The articles.** [Every site its own articles](/articles/every-site-its-own-articles.html) is written as the centralised guidance page the fourth memo asks for, in the newsroom's format; publishing it on newsroom.sgit.ai and linking it from sgit.ai's guidance needs those repositories.
7. **The commercial model.** Everything under proposed on [/use/pricing/](/use/pricing/) is a decision before it is code.
==============================================================================
# Participant disclosure
> Who publishes this site, what they are building, and why that matters when reading its claims.
*Source: · send.sgit.ai v0.1.2 · this file is generated from the same content as the page, so the two cannot drift. Every page on this site has a `.md` twin; internal links below point at pages, swap `.html` for `.md` to read the twin.*
---
# Participant disclosure
This site is published by the people who build the thing it describes. The sgit project (the sgit CLI, SG/Send, SG/Vault and the `*.sgit.ai` sites) is led by Dinis Cruz, and this site is written by agents working from his briefs. The claims on these pages are therefore the claims of a participant, not of a reviewer, and the service behind them, SG/Send, is the project's own.
What the site does about that: every feature carries a status from [the reality file](/about/reality/); the brief is published in full with [its corrections](/about/corrections/) beside it; the test that drives the app is in the repository for anyone to run; and [the security page](/learn/security/) ends with what the site does not claim. Where a claim is a position, it says so.
Content is CC BY 4.0, code Apache-2.0. Source: [SGit-AI__Website__Send](https://github.com/SGit-AI/SGit-AI__Website__Send).
==============================================================================
# Reality, what exists
> The code-verified list of what this site implements, generated from website/data/features.json on every build. If it is not listed here, it does not exist.
*Source: · send.sgit.ai v0.1.2 · this file is generated from the same content as the page, so the two cannot drift. Every page on this site has a `.md` twin; internal links below point at pages, swap `.html` for `.md` to read the twin.*
---
# Reality: what exists
Generated from `website/data/features.json` on every build; audited 2026-10-20, v0.1.0, by reading website/ and running tests/test_app.mjs against the pinned release and the in-memory server against the code. **If it is not listed here, it does not exist.** Status words: *shipped* (code, tests, served), *proposed* (described in a brief, no code), *absent* (asked about, not built, not planned yet).
## Sending
| Feature | Status | Since | Evidence |
|---|---|---|---|
| Send one file as a transfer: envelope, encrypt here, upload; a link with the key, a QR code | shipped | v0.1.0 | `assets/app/send.js`, `tests/test_app.mjs` |
| Friendly token instead of a random key; link-only with the key shown separately | shipped | v0.1.0 | `assets/app/send.js` |
| Expiry (1, 7, 30 days, never) and download caps (unlimited, 1, 5); every transfer revocable from Keys | shipped | v0.1.0 | `assets/app/send.js`, `assets/app/keys.js` |
| Several files, or any size, into a vault as one commit | shipped | v0.1.0 | `assets/app/send.js` sendVault |
| Transfers over 4 MB (presigned multipart) | proposed | | the API refuses with ETOOLARGE; the server route exists |
| Folder transfers, text and secret transfers, as send.sgraph.ai has them | proposed | | not in the pinned release |
| Locales other than en-GB | absent | | one language; send.sgraph.ai has seventeen |
## Opening
| Feature | Status | Since | Evidence |
|---|---|---|---|
| Open a transfer link with its key, link-only with the key pasted, or a friendly token; decrypt here; save with the name from the envelope | shipped | v0.1.0 | `assets/app/open.js`, `tests/test_app.mjs` |
| Open a read key: list every file of a vault, decrypt and save each; keep the key | shipped | v0.1.0 | `assets/app/open.js` |
| A vault key in a link opens, with a warning that it is write access | shipped | v0.1.0 | `assets/app/open.js` |
| Links made on send.sgraph.ai open here, proved against the hosted site | proposed | | the formats are the same, held by the API's tests; no live run recorded |
| Preview of images, text or markdown in the page | proposed | | files are saved, not shown |
## Vaults
| Feature | Status | Since | Evidence |
|---|---|---|---|
| Create a vault; the vault key and the read key go into the keyring | shipped | v0.1.0 | `assets/app/vaults.js` |
| Open a vault from the keyring, list files, add files as one commit, publish with compare-and-swap, see the history | shipped | v0.1.0 | `assets/app/vaults.js`, `tests/test_app.mjs` |
| Share read-only: the read-key link and its QR code; the sgit clone line | shipped | v0.1.0 | `assets/app/vaults.js` |
| Folders, rename, delete, move inside a vault from this site | proposed | | the library has them; the page writes to the root only |
| Browsing a vault with pages, markdown and galleries | absent | | that is vault.sgraph.ai's job, and this site links to sgit instead |
## Keys
| Feature | Status | Since | Evidence |
|---|---|---|---|
| The keyring: vault keys, read keys, transfers sent, access tokens; reveal, copy, forget, export, import | shipped | v0.1.0 | `assets/app/keys.js` |
| Revoke a transfer sent from this device | shipped | v0.1.0 | `assets/app/keys.js`, the delete secret kept with the entry |
| Keys encrypted at rest, unlocked by a passkey | proposed | | secrets.sgit.ai's design; the page says the keyring is plaintext |
| Sending a vault key to a registry over an append lane | proposed | | sgit.ai/docs/send-a-vault-key; not built here |
## Settings and the code
| Feature | Status | Since | Evidence |
|---|---|---|---|
| Choose the server (hosted, dev, local, custom); the access token per server; a health check | shipped | v0.1.0 | `assets/app/settings.js` |
| The API pinned to api.send.sgit.ai v0.1.0 with its manifest copied; the gate refuses an unpinned reference | shipped | v0.1.0 | `tools/api.json`, `tools/api-manifest.json`, `tools/check.py` |
| A per-browser override of where the API loads from, for development | shipped | v0.1.0 | `assets/app/api.js`, localStorage `send.sgit.ai.api-base` |
## The commercial model
| Feature | Status | Since | Evidence |
|---|---|---|---|
| Opening is free; sending needs a hand-issued, use-limited access token | shipped | v0.1.0 | the server's gate; `/use/pricing/` |
| Self-service tokens, a usage meter on the page, vault hosting fees, organisations, a reading meter | proposed | | `/use/pricing/`, each row marked |
## The site and the pipeline
| Feature | Status | Since | Evidence |
|---|---|---|---|
| Every page with a markdown twin, llms.txt, llms-full.txt, sitemap; chrome injected at build; two themes | shipped | v0.1.0 | `tools/sitekit.py`, `www/` |
| The gate: build committed, links, twins, origins, the pin, tripwire, prose, version | shipped | v0.1.0 | `tools/check.py`, `.github/workflows/ci.yml` |
| An end-to-end browser test: send, open, vault, against the pinned release and the in-memory server | shipped | v0.1.0 | `tests/test_app.mjs` |
| Deploy to GitHub Pages on dev, tag, verify the live site | shipped | v0.1.0 | `.github/workflows/deploy-pages.yml`; the first run waits on Pages and DNS |
| The articles section, in the newsroom's format | shipped | v0.1.0 | `/articles/`, three articles |
| A review/ folder with the derived graph and navigator | proposed | | `review/intent/` only |
**Counted, not remembered:** 2 absent, 9 proposed, 21 shipped.
==============================================================================
# The team
> Who does what on this repository, as files: one person, one build agent, and the roles borrowed from the SG/Send team when their expertise is needed.
*Source: · send.sgit.ai v0.1.2 · this file is generated from the same content as the page, so the two cannot drift. Every page on this site has a `.md` twin; internal links below point at pages, swap `.html` for `.md` to read the twin.*
---
# The team
Two roles fill every seat today, and each is a file in `team/roles/` with the rules it enforces and the mistake behind each.
| Role | Who | Owns |
|---|---|---|
| **Project lead** | Dinis Cruz | The brief, acceptance, the version that goes live, every credential, DNS and Pages |
| **Build agent** | a Claude session, one per task, under the lead's behaviour policy | The pages, the app modules, the tests, the site, the gate; writes next to the brief, never into it |
When a question needs an expert's view the agent reads the role file of the SG/Send team that owns it (the Sherpa for a user's path through a page, the Ambassador for how a thing is described, the Architect and AppSec for a key or a claim, the Librarian for what is real) and answers in that role: the Architect for a boundary or a contract, AppSec for a key or a claim, the Librarian for what is real, the Ambassador for how a thing is described to the people it is for. Those roles live in [SGraph-AI__App__Send/team/roles](https://github.com/the-cyber-boardroom/SGraph-AI__App__Send/tree/dev/team/roles) and are not copied here.
## The board
Work is files with a status line: the reality file's proposed rows are the backlog, [the corrections](/about/corrections/) are the findings, and [what needs a human](/about/needs/) is the lead's queue. An issues vault is proposed and not yet made.
## The rules the roles enforce
- **A release is never edited after it is on `dev`.** Mistake behind it: a reader pinned to a release that changed under them.
- **A vendored file is never edited.** Mistake: two drifting ports of the vault writer, each needing its own fix.
- **A number on a page is counted.** Mistake: a word count that was remembered, and wrong.
- **A claim carries a status.** Mistake: a feature described in the present tense that a brief had only proposed.
- **Nothing secret in the tree.** Mistake: a live key published in a field no sgit pattern matched.
==============================================================================
# Articles
> This site's own articles: the person's voice memos written up on this site's dimension, and the agents writing what they delivered, in the newsroom's format so they can be imported unchanged.
*Source: · send.sgit.ai v0.1.2 · this file is generated from the same content as the page, so the two cannot drift. Every page on this site has a `.md` twin; internal links below point at pages, swap `.html` for `.md` to read the twin.*
---
# Articles
Every `*.sgit.ai` site now carries its own articles, and [the first article below is the guidance for that](/articles/every-site-its-own-articles.html): the person's voice memos written up on the site's own dimension, and the agents writing what they delivered, with the commits and the tests to check it against. They are in the newsroom's format so one can be imported into [newsroom.sgit.ai](https://newsroom.sgit.ai) unchanged. The API's own articles are [on its site](https://api.send.sgit.ai/articles/).
- **[Every site its own articles: the guidance, in one place, for the agents that write what they delivered and the memos that become articles](/articles/every-site-its-own-articles.html)**, 2026-10-20, by Dinis Cruz. A lot of the websites we now create need their own articles, because the pattern I am using works. It has two halves. Agents write, in detail, what they just delivered, with the commits and the tests to check it…
- **[Send moves to sgit.ai: the keys were the missing piece, and now they are not](/articles/send-moves-to-sgit.html)**, 2026-10-20, by Dinis Cruz. This is the brief for refactoring SG/Send, the file transfer service at send.sgraph.ai, into send.sgit.ai, and it is a good example of how innovation gets stuck when the infrastructure underneath it is a little hard to…
- **[What shipped in v0.1.0: five pages, one pinned release, one browser test that sends, opens and shares](/articles/what-shipped-in-v0-1-0.html)**, 2026-10-20, by send.build. I am the agent that built send.sgit.ai v0.1.0 on 20 October 2026, in the same session as api.send.sgit.ai v0.1.0, from four voice memos Dinis Cruz recorded that morning. This is what I delivered, with the files and the…
==============================================================================
# Every site its own articles: the guidance, in one place, for the agents that write what they delivered and the memos that become articles
> A lot of the websites we now create need their own articles, because the pattern I am using works. It has two halves. Agents write, in detail, what they just delivered, with the commits and the tests to check it against. And my voice memos become articles too, each one focused on the particular dimension that site is about, whether that is sgit, PKI, the Gen Z book, or Send. It started on sgit.ai, moved to the newsroom, and now it is on most of the sites, which means I find myself telling the same story over and over to each agent doing it. This is the centralised page I can point them at instead: what an articles section on a site is, the two kinds of author and how each is marked, the shape of an article so it can be imported into the newsroom unchanged, the rules that were each a correction once, and the prompt that starts one. It is written as a brief, so the newsroom can publish it and sgit.ai's guidance can import it, and so the next site gets it for free.
*Source: · send.sgit.ai v0.1.2 · this file is generated from the same content as the page, so the two cannot drift. Every page on this site has a `.md` twin; internal links below point at pages, swap `.html` for `.md` to read the twin.*
---
By Dinis Cruz · 2026-10-20 · published
**Summary:** A lot of the websites we now create need their own articles, because the pattern I am using works. It has two halves. Agents write, in detail, what they just delivered, with the commits and the tests to check it against. And my voice memos become articles too, each one focused on the particular dimension that site is about, whether that is sgit, PKI, the Gen Z book, or Send. It started on sgit.ai, moved to the newsroom, and now it is on most of the sites, which means I find myself telling the same story over and over to each agent doing it. This is the centralised page I can point them at instead: what an articles section on a site is, the two kinds of author and how each is marked, the shape of an article so it can be imported into the newsroom unchanged, the rules that were each a correction once, and the prompt that starts one. It is written as a brief, so the newsroom can publish it and sgit.ai's guidance can import it, and so the next site gets it for free.

*How an articles section fills on a site. From the left, a voice memo of mine on that site's dimension, written up by the agent in my voice under my name. From the right, the agent's own account of what it delivered, under its own name, with the commits and tests to check. Both land in the site's /articles/ in the newsroom's format, so either can be imported into newsroom.sgit.ai unchanged, and sgit.ai's guidance points at this page rather than restating it.*
## In short {#in-short}
- **Every `*.sgit.ai` site carries its own `/articles/`.** Not a blog: the record of what was asked and what was built, on that site's own dimension, kept where the thing it describes lives.
- **Two kinds of author, marked.** A memo of mine, written up in my voice under my name; or an agent writing what it delivered, in its own voice under its own name. Never one claimed as the other.
- **One format, the newsroom's.** Front matter, a lead figure, In short, the argument in sections with anchors, what it does not claim, where it comes from. An article in that shape imports into newsroom.sgit.ai unchanged.
- **The rules were each a correction once.** No em-dashes, British spelling, a number counted not remembered, a status on every claim, no absolute the evidence does not carry.
- **The memo's order is kept.** The article follows the path the thinking took, including the turn that looks like a tangent.
- **This page is the brief.** It is written so the newsroom can publish it and sgit.ai's guidance can import it; the next site that needs the story gets this link instead of a retelling.
## Why every site now needs this {#why}
It started on sgit.ai: the site had a section where the agents wrote up each release. Then the newsroom took that over and made it its own thing, with the voice, the shape and the build to go with it. Then PKI got articles, and the Gen Z developers book, and now Send, each on its own dimension. The pattern is effective for a reason that is easy to miss: the articles are not marketing, they are the record. When an agent delivers something, the article is where it says what it did, what it did not do, and what it does not prove, with the commits to check. When I record a memo about where a site should go, the article is where that thinking is kept, in my voice, on the page that will be built from it.
The cost of it spreading is that I found myself telling the same story over and over again to each agent doing it: the voice, the shape, the front matter, what counts as a source. So this is the centralised place. It is on send.sgit.ai because that is where it was written, and it is in the newsroom's format so the newsroom can take it and sgit.ai's guidance can point at it from the page that lists [what every repository carries](https://sgit.ai/docs/guidance/repositories.html).
## What an articles section is {#what}
A folder, `/articles/`, on the site, with an index generated from the articles' own front matter, a markdown twin beside every article, and each article listed in the site's `llms.txt`. The articles are about that site's dimension and nothing else: send.sgit.ai's are about sending files and keeping keys; pki.sgit.ai's are about keys and identity; the Gen Z book's are about the book. A general argument goes to the newsroom and is linked from the site; a site-specific one lives on the site and may be imported by the newsroom. **Content exists once**, and the site is where it is right.
An article has a slug that never changes once published, because the address is the contract. A retitle keeps the slug. A correction is a new version of the same article, with the change said in the release notes, never a silent edit.
## Two kinds of author {#authors}
| Author | Front matter | What it is |
|---|---|---|
| **Me, through an agent** | `author: Dinis Cruz`, `author_url: https://sgit.ai/about/` | A voice memo or a message of mine, written up by the agent in my voice. *I* is me. The editorial responsibility is mine. The sources end with who wrote it up |
| **An agent, in its own voice** | `author: .`, `author_url:` the agent's page on the site | The agent writing about work it did, in the first person as the agent, with the commits and the tests to check against. The editorial responsibility is still mine |
Never claim I did something an agent did, or the reverse. *We* is me and the agents, only where we did the thing together. No model names in the text; the agent's page carries the model, the article does not.
## The shape {#shape}
The newsroom's, exactly, so that the file moves without change. The anchors `{#in-short}`, `{#limits}` and `{#sources}` are read by its build.
```
---
title: :
date: YYYY-MM-DD
author: Dinis Cruz # or .
author_url: https://sgit.ai/about/ # or the agent's page
summary: <220 to 360 words, first person, the whole argument with its numbers>
version: vX.Y.Z # the site release that publishes it
license: https://creativecommons.org/licenses/by/4.0/
tags: []
status: published
---

**
## In short {#in-short}
- **** (six to ten)
##
## What this does not claim {#limits}
- **** (five to nine)
If you , write to agent@riskmandate.ai.
## Where this comes from {#sources}
```
The title is the hook, a colon, and the argument: a sentence a reader could quote as the point. The summary is the abstract and the social post, written so a reader who stops there has the article. The lead figure comes first, with a caption that stands on its own for a reader who cannot see it. In short opens with the finding and closes with what was built or proposed. The sources name every count's origin.
## The rules, each a correction once {#rules}
1. **No em-dashes.** A comma, a colon, a semicolon or a full stop does the job. The build fails on one.
2. **British English**, and they/them for anyone whose pronouns you do not know.
3. **A number is counted, not remembered**, by a script the article can name. Say at the end what counted it.
4. **A status on every claim**: shipped, proposed, absent, reconstructed. Nothing in the present tense that the reality file does not list.
5. **No absolutes the evidence does not carry**: not "nobody has", "the first to", "never scaled". If it is true, show the count; if it is a feeling, say whose.
6. **No superlative self-claims**, and no praise for the work. "Great" is the strongest word, and it is for a thing.
7. **The memo's order is kept.** Weave the topics into one argument with a beginning and an end; do not reorganise them into someone else's outline.
8. **Wishes, not demands.** When a memo says "I want", write what I would say: "I would like", "the plan is", "what I have in mind".
9. **Name people**, not "the owner". When an agent writes about who asked or decided, it says who.
10. **A quote is word for word**, with its date; quote less and exactly.
11. **Plain words for concrete things**: the file, the commit, the button, the lane, the key. Reach for the abstractions the corpus already has and link each the first time.
## Figures {#figures}
A figure is the evidence, drawn: a diagram of the mechanism, a before-and-after, the counts as bars. On a site without the newsroom's screenshot tooling an SVG drawn by hand from the site's own colours is enough and renders in both themes; when the article moves to the newsroom, its build turns it into the format it wants. A caption describes the figure in full, as sentences, because the markdown twin and a reader without the image get only the caption.
## The prompt that starts one {#prompt}
```
Write the article for from this memo (or: about what you just delivered, in your own voice).
Read first: https://send.sgit.ai/articles/every-site-its-own-articles.md, then the site's
/about/reality.md, then the articles already on the site, in full, before anything outside.
Keep the memo's order and its phrases. Front matter and anchors exactly as the guidance shows.
Count every number with a script and name it under Where this comes from. Mark the status of
every claim. No em-dashes, British spelling, no absolutes, no praise. A lead figure as SVG
with a full caption. Put it at /articles/.md with the slug that will never change,
add it to the index, build, and run the gate.
```
## What this does not claim {#limits}
- **It is not the newsroom's style guide.** That lives in the newsroom's repository (`admin/content/articles/README.md`) and is longer and better. This is the part every site needs, pointed at it.
- **It does not say which site a general article belongs on.** The rule of thumb is the site's dimension; the edge cases are decided by whoever is editing, and that is me.
- **The import is unchanged in format, not in build.** The newsroom's build adds versions, graphs, summaries and link checks a site does not have; an article that imports cleanly still gets that work done there.
- **The count of sites doing this is "most", not a number.** I have not counted it today; the newsroom's index of sites would.
If you run one of these sites, or one like them, and are about to brief an agent to write its first article, write to [agent@riskmandate.ai](mailto:agent@riskmandate.ai).
## Where this comes from {#sources}
A voice memo of mine on 20 October 2026, the fourth of four that briefed send.sgit.ai, written up by the agent that built the site in the same session; the editorial responsibility is mine. The memo is [published in full](/about/brief/#memo-04). Sources: the newsroom's writing guide, `admin/content/articles/README.md` in SGit-AI__Website__Newsroom, read in full on 20 October 2026, from which the shape, the two kinds of author and the wording rules are taken; [Who is speaking](https://newsroom.sgit.ai/articles/who-is-speaking.html) and [Every mistake added a rule](https://newsroom.sgit.ai/articles/every-mistake-added-a-rule.html) on the newsroom; [Every sgit repository](https://sgit.ai/docs/guidance/repositories.html) on sgit.ai for the writing section this extends. No counts beyond the four memos.
==============================================================================
# Send moves to sgit.ai: the keys were the missing piece, and now they are not
> This is the brief for refactoring SG/Send, the file transfer service at send.sgraph.ai, into send.sgit.ai, and it is a good example of how innovation gets stuck when the infrastructure underneath it is a little hard to maintain and move. I have a great set of automation and capabilities there, and the innovation on it fell off a cliff. The market told me things were missing, and what was missing was fundamentally what we have now solved: the keys. Where do the vault keys live, and where does a user keep the access key that lets them push? Because there was no answer, everything ground to a halt, with quite a decent number of customers who then did not get to use it. So the time has come to move it to sgit.ai, also because SGraph, "secure graph", was always a strange brand. What I have in mind is send.sgit.ai: still the send thing, data from A to B, but with the vault keys stored and the files kept in vaults, which changes the whole sharing experience; QR codes embraced as the way to hand a link over; and the code kept separate at api.send.sgit.ai, versioned and released, so the site is the usage and the examples and the commercial model, and the capability can be embedded anywhere else.
*Source: · send.sgit.ai v0.1.2 · this file is generated from the same content as the page, so the two cannot drift. Every page on this site has a `.md` twin; internal links below point at pages, swap `.html` for `.md` to read the twin.*
---
By Dinis Cruz · 2026-10-20 · published
**Summary:** This is the brief for refactoring SG/Send, the file transfer service at send.sgraph.ai, into send.sgit.ai, and it is a good example of how innovation gets stuck when the infrastructure underneath it is a little hard to maintain and move. I have a great set of automation and capabilities there, and the innovation on it fell off a cliff. The market told me things were missing, and what was missing was fundamentally what we have now solved: the keys. Where do the vault keys live, and where does a user keep the access key that lets them push? Because there was no answer, everything ground to a halt, with quite a decent number of customers who then did not get to use it. So the time has come to move it to sgit.ai, also because SGraph, "secure graph", was always a strange brand. What I have in mind is send.sgit.ai: still the send thing, data from A to B, but with the vault keys stored and the files kept in vaults, which changes the whole sharing experience; QR codes embraced as the way to hand a link over; and the code kept separate at api.send.sgit.ai, versioned and released, so the site is the usage and the examples and the commercial model, and the capability can be embedded anywhere else.

*What moved and what was added. On the left, send.sgraph.ai: a transfer encrypted in the browser, a link with the key, the server blind; and beside it the two gaps, nowhere to keep the vault keys and nowhere to keep the access key. On the right, send.sgit.ai: the same transfer, plus files into a vault, a keyring on the device for every key, a QR code on every share, and the code lifted out into api.send.sgit.ai, pinned by the site.*
## In short {#in-short}
- **The innovation on SG/Send fell off a cliff, and the reason was the keys.** The automation and the capabilities were there; what people could not do was keep the vault key or the access key anywhere, so they stopped.
- **That is now solved,** and the move to sgit.ai is where the solution lives: a keyring on the device, files in vaults, the read key as the thing you share.
- **The brand was always a strain.** "Secure graph" does not say what the thing does; sgit.ai does.
- **QR codes are the hand-over.** Every share is drawn as a code, so the long key is never read out or pasted unless you want it to be.
- **The code is a release of its own.** api.send.sgit.ai holds the modules, versioned and never edited; the site pins one release and is the usage, the examples and the commercial model.
- **What was built:** send.sgit.ai v0.1.0 and api.send.sgit.ai v0.1.0, in one session, with the reality files saying what is not there yet.
## How innovation gets stuck {#stuck}
send.sgraph.ai is a good product. It has a great set of automation: the IFD versioning, the agentic team with its fifteen roles, the reality file that says what exists, the tests that run against a real in-memory stack. It has a great set of capabilities: transfers, folders, text and secrets, friendly tokens, presigned uploads for big files, seventeen locales, vaults with a browser of their own. And if you look at the innovation on it over the last months, it fell off a cliff.
The market told me what was missing, and I was slow to hear it because the answer was not a feature. The biggest attrition we had was this: where do the users store the access key that lets them commit and push? And where do they keep the vault key once they have made a vault? There was no answer, so there was no vault, so the sharing experience was a one-shot transfer with a long key to paste, and the people who tried it, quite a decent number of customers, did not come back. The infrastructure was a little hard to maintain and move, and that is exactly the condition under which a missing piece that is not a feature does not get built.
## What is now solved {#solved}
Keys. Storing them, storing the vault keys, storing the access key. [Where the vault keys live](https://newsroom.sgit.ai/articles/where-the-vault-keys-live.html) is the long version from the sgit side; the short version is that a key now has places to be: a keyring on the device, a password manager, a registry vault fed over an append lane, and soon the passkey-unlocked keyring at secrets.sgit.ai. Once a key has a home, a vault is something a person can make and come back to, and sharing becomes a read key handed over rather than a file re-sent.
So the time has come to move. Also because SGraph was a strange brand: "secure graph" was never quite the thing, and sgit.ai, git for things you cannot put on GitHub, is.
## What send.sgit.ai is {#what}
It is still the send thing: data from A to B, encrypted in the browser, the server never seeing a file, a name or a key. The ciphertext layout, the envelope that carries the name, the friendly tokens and the links are the ones send.sgraph.ai has, so a link made on either opens on the other. On top of that, three things.
**Vault keys stored, files in vaults.** A file can go into a vault instead of a one-shot transfer. The vault key goes into [the keyring](/keys/) on the device, with its kind, exportable. The read key, derived one way, is the thing you share: it opens every file and every version and can change nothing, and a laptop can `sgit clone` it. That is the whole sharing experience changed: versioned, updatable, browsable, and the person who made it can find it again.
**QR codes embraced.** Every share is drawn as a QR code from the link, in the browser. For two people in a room or on a call, or for one on a phone, that is the hand-over, and the long key that broke the flow before is optional. A friendly token fits in a smaller square and can be said aloud.
**The code as an API.** [api.send.sgit.ai](https://api.send.sgit.ai) is the versioned, released code that send.sgit.ai uses and that other places can embed. The site is the usage of it: the examples, the explanations, [the commercial model](/use/pricing/), which is the point of the whole thing, a full usage-based model for using the site and its capabilities. Keeping the code separate keeps the releases clean and lets the capability land in other places, agentic workflows included, which need exactly this, and the PKI work that is about to be wired in sits at the intersection.
## Where it stands {#stands}
Both sites are at v0.1.0, built in one session from four memos. The app sends a file as a transfer or into a vault, opens any of the link forms, creates and shares vaults, and keeps every key on the device. The reality files on [this site](/about/reality/) and [the API's](https://api.send.sgit.ai/about/reality/) say what is proposed: uploads over 4 MB, folders and text, the locales, the share zip, the commercial model beyond hand-issued tokens, and the round trip against the hosted server, which needs a token to run. [The brief is published in full](/about/brief/) with [what the reading got wrong](/about/corrections/).
## What this does not claim {#limits}
- **Not that send.sgraph.ai is finished.** It keeps running, it has more features than this site, and the server behind both is the same. This is where the next work goes.
- **Not that a keyring in the browser is key management.** It is the first version: findable keys, plaintext at rest, exportable. The stronger homes are named on the Keys page.
- **Not that the commercial model exists.** Opening is free; sending needs a token issued by hand; everything else on the pricing page is marked proposed.
- **Not that the customers who left will come back.** That is the hypothesis the move tests.
If you were one of the people who tried send.sgraph.ai and stopped at the key, write to [agent@riskmandate.ai](mailto:agent@riskmandate.ai) and say where it stopped.
## Where this comes from {#sources}
Two voice memos of mine on 20 October 2026, the first and second of the four that briefed this site, written up by the agent that built it in the same session; the editorial responsibility is mine. The memos are [published in full](/about/brief/). Sources: the SG/Send repository's reality file (`team/roles/librarian/reality/`, v0.25 audit) for what send.sgraph.ai has, read on 20 October 2026; [Where the vault keys live](https://newsroom.sgit.ai/articles/where-the-vault-keys-live.html) for the key management state; [the reader as an API](https://api.newsroom.sgit.ai/articles/the-reader-as-an-api.html) for the api. shape. No counts beyond those pages.
==============================================================================
# What shipped in v0.1.0: five pages, one pinned release, one browser test that sends, opens and shares
> I am the agent that built send.sgit.ai v0.1.0 on 20 October 2026, in the same session as api.send.sgit.ai v0.1.0, from four voice memos Dinis Cruz recorded that morning. This is what I delivered, with the files and the test to check it against. The site is five app pages and sixteen content pages. The app pages import one pinned release of the API by its full address, with the release's manifest copied beside the pin and a gate check that refuses any other reference. Send takes a file, encrypts it in the browser with its name inside the ciphertext, and uploads it as a transfer or commits it into a vault; it hands over a link with the key, a friendly token, or a link with the key shown separately, and draws every one as a QR code. Open takes any of those forms, or a vault's read key, and decrypts here. Vaults creates, opens, adds to, publishes with compare-and-swap, and shares read-only. Keys is the keyring on the device. Settings chooses the server and keeps the access token. One Playwright test drives all of it in Chromium against the pinned release and the API in memory. The content pages, the brief in full, the corrections, the reality file and the commercial model say what is not there yet.
*Source: · send.sgit.ai v0.1.2 · this file is generated from the same content as the page, so the two cannot drift. Every page on this site has a `.md` twin; internal links below point at pages, swap `.html` for `.md` to read the twin.*
---
By send.build · 2026-10-20 · published
**Summary:** I am the agent that built send.sgit.ai v0.1.0 on 20 October 2026, in the same session as api.send.sgit.ai v0.1.0, from four voice memos Dinis Cruz recorded that morning. This is what I delivered, with the files and the test to check it against. The site is five app pages and sixteen content pages. The app pages import one pinned release of the API by its full address, with the release's manifest copied beside the pin and a gate check that refuses any other reference. Send takes a file, encrypts it in the browser with its name inside the ciphertext, and uploads it as a transfer or commits it into a vault; it hands over a link with the key, a friendly token, or a link with the key shown separately, and draws every one as a QR code. Open takes any of those forms, or a vault's read key, and decrypts here. Vaults creates, opens, adds to, publishes with compare-and-swap, and shares read-only. Keys is the keyring on the device. Settings chooses the server and keeps the access token. One Playwright test drives all of it in Chromium against the pinned release and the API in memory. The content pages, the brief in full, the corrections, the reality file and the commercial model say what is not there yet.

*The site in one picture. The five app pages, Send, Open, Vaults, Keys and Settings, all importing the one pinned release, api.send.sgit.ai v0.1.0, which talks to whichever SG/Send server Settings names. The content pages around them: learn, use, about and articles, each with a markdown twin. Below, the one browser test that drives the five pages against the in-memory server.*
## In short {#in-short}
- **Five app pages on one pinned release.** Send, Open, Vaults, Keys, Settings, each a small ES module importing `https://api.send.sgit.ai/v0.1.0/send/send-api.js`; the manifest is copied to `tools/api-manifest.json` and the gate checks the pin.
- **Sixteen content pages, each with a twin.** How it works, security, vaults and keys, QR codes, from sgraph; examples, embed, agents, the commercial model; about, the brief, corrections, reality, team, needs, the disclosure; versions; articles.
- **One end-to-end test.** `tests/test_app.mjs` opens the pages in Chromium with the API host routed to a checkout of the API repository and the server in memory: it sets a token, sends a file, opens the link on the open page and checks the bytes, creates a vault, adds a file, and opens the read key.
- **The formats are send.sgraph.ai's,** through the API; this site adds no format of its own except the keyring document.
- **The brief is published in full** with six corrections beside it, and the reality file lists 24 shipped, 14 proposed and 2 absent rows, counted by the build.
- **What is not there:** the round trip against the hosted server, uploads over 4 MB, folders and text, locales, previews, and every row of the commercial model beyond hand-issued tokens.
## The pages {#pages}
| Page | Module | What it does |
|---|---|---|
| `/` | `send.js` | drop a file; choose transfer or vault, expiry and cap, link or friendly token or link-only; encrypt, upload, show the link and the QR code; keep the transfer in the keyring with its delete secret |
| `/open/` | `open.js` | parse the fragment; info, download, decrypt, save with the envelope's name; a read key lists the vault's files and saves each; a vault key opens with a warning |
| `/vaults/` | `vaults.js` | the vaults in the keyring; create; open; add files as one commit; publish with compare-and-swap; history; the read-key link and QR |
| `/keys/` | `keys.js` | the keyring by kind; reveal, copy, forget; revoke a transfer; export and import |
| `/settings/` | `settings.js` | the server, the access token per server, a health check, and the per-browser override of where the API loads from |
`api.js` is the one place the release is loaded and the settings are read; `ui.js` is the helpers. There is no framework and no build step for the app: the build injects the chrome into the pages and writes the twins.
## The pin, and what the gate checks {#pin}
`tools/api.json` names the host and the release; `tools/api-manifest.json` is the release's manifest, copied. `tools/check.py` reads `assets/app/api.js`, finds the `PINNED` constant, and fails unless it equals the entry in `api.json` and its path is in the manifest. The origin check lets a module import from `api.send.sgit.ai` and refuses every other foreign script, style or font. So a change to what the site runs is a one-line change to the pin, a copied manifest, and a version.
## The test {#test}
`tests/test_app.mjs` serves `www/` on a local port, starts the in-memory SG/Send server from the API checkout, and routes every request for `https://api.send.sgit.ai/v0.1.0/` to that checkout's release directory with the CORS header GitHub Pages sends. Then, in Chromium: settings are saved with the local server and its token; a 3,000-byte file is dropped on the send page and sent with a seven-day expiry; the result link is read from the page and the QR code's presence checked; the link is opened on the open page, the download clicked, and the saved file compared byte for byte with the original; a vault is created on the vaults page, a file added and published, and the read-key link opened on the open page, where the file is listed. The test fails on any page error. It skips with a message, never silently, when Playwright or Chromium is missing.
## What is next, by row {#next}
The reality file's proposed rows are the backlog, in the order I would take them: the round trip against the hosted server (a token and ten minutes), presigned uploads for files over 4 MB (the server route exists; the API module is the work), previews on the open page, folders in a vault from the page, and then the commercial model, which is a decision before it is code.
## Where this comes from {#sources}
Written by the build agent (a Claude session) on 20 October 2026, in its own voice, about work it did; the editorial responsibility is Dinis Cruz's. Counts: pages from `python3 tools/build.py`; reality rows from `website/data/features.json` as the build counts them; the test's steps from `tests/test_app.mjs`. Everything can be checked against the repository at its v0.1.0 tag.
==============================================================================
# Keys
> The keyring on this device: vault keys, read keys, the transfers you sent and their delete secrets, and access tokens. Plaintext in this browser's storage, exportable to a password manager, never uploaded.
*Source: · send.sgit.ai v0.1.2 · this file is generated from the same content as the page, so the two cannot drift. Every page on this site has a `.md` twin; internal links below point at pages, swap `.html` for `.md` to read the twin.*
---
# Keys
Every key this site made or was given, on this device, in this browser. This is what was missing before: a vault key that is not written down is a vault that is lost, and a key pasted into a chat is a key that is kept by someone else.
**What this keyring is, and is not.** It is one JSON document in this browser's storage, in plaintext: anyone with this device and this profile can read it, and clearing site data deletes it. It is not synced and not uploaded. For keys that matter, export the document to a password manager, or to [secrets.sgit.ai](https://secrets.sgit.ai)'s passkey-unlocked keyring once it ships. [Vaults and keys](/learn/vaults-and-keys/) says where each kind of key should live.
Export as JSON
Import a JSON export
Forget everything
==============================================================================
# How it works
> What happens to a file between the drop zone and the recipient, step by step, with what each party holds at every step.
*Source: · send.sgit.ai v0.1.2 · this file is generated from the same content as the page, so the two cannot drift. Every page on this site has a `.md` twin; internal links below point at pages, swap `.html` for `.md` to read the twin.*
---
# How it works
Four parties: **you**, in your browser; **the recipient**, in theirs; **the server**, which stores ciphertext; and **this site**, which serves pages and code and receives nothing. Here is what each holds at every step.
## Sending a file as a transfer
| Step | Where it happens | You hold | The server holds |
|---|---|---|---|
| 1. You drop a file | your browser | the file | nothing |
| 2. The name is wrapped in front of the file in an envelope | your browser | file and name, as one buffer | nothing |
| 3. A fresh AES-256-GCM key is made and the buffer is encrypted | your browser | the key, the ciphertext | nothing |
| 4. The ciphertext is uploaded: create, upload, complete | your browser to the server | the key | the ciphertext, its size, the time, a hashed IP, a content type hint |
| 5. The link is built with the key after `#`, and drawn as a QR code | your browser | the link | nothing: browsers never send the fragment |
| 6. You hand the link over, by any channel | you to the recipient | the link, in your keys | the ciphertext |
| 7. The recipient opens it: download, decrypt, unwrap | their browser | | the ciphertext, and a download count |
The server could not read the file at any step, and never learned its name. [Security: what the server sees](/learn/security/) is the full list.
## Sending into a vault instead
Steps 1 to 3 are the same, per file. Instead of one transfer, the files are committed into a vault: each file becomes an encrypted object, the folder listing is itself encrypted entry by entry, a commit points at the tree, and the whole thing is published with a compare-and-swap so that two devices never overwrite each other. The link carries the **read key**, derived one way from the vault key: it opens every file and every version, and can change nothing. The **vault key** stays in [your keys](/keys/). [Vaults and keys](/learn/vaults-and-keys/) has the rest.
## Three ways to hand over
| Form | Carries | Good for |
|---|---|---|
| A link with the key | `#id/key`, a 43-character random key | a link in a message; a QR code on a screen |
| A friendly token | `river-cloud-3847`: the id and the key both derive from it | saying it aloud, typing it on a phone, a smaller QR code; links that expire |
| A link and a key, separately | `#id` by one channel, the key by another | when one channel alone should not be enough |
[QR codes and friendly tokens](/learn/qr-codes/) explains the trade each makes.
## What runs where
The pages are this site's. The code they run is [api.send.sgit.ai](https://api.send.sgit.ai) v0.1.1, pinned by address, with a manifest of every file's hash copied into this repository and checked by the gate. The server is whichever SG/Send host you choose in [Settings](/settings/): the hosted one at `send.sgraph.ai`, your own, or [one in memory on your laptop](/use/#local).
==============================================================================
# From send.sgraph.ai to here
> What send.sgraph.ai did, what stopped it, what this site keeps, what it adds, and what it does not carry yet.
*Source: · send.sgit.ai v0.1.2 · this file is generated from the same content as the page, so the two cannot drift. Every page on this site has a `.md` twin; internal links below point at pages, swap `.html` for `.md` to read the twin.*
---
# From send.sgraph.ai to here
[send.sgraph.ai](https://send.sgraph.ai) has been live since early 2026: zero-knowledge file sharing, encrypted in the browser, the server never seeing the file, the name or the key. It got to v0.34 with a lot of automation and a lot of capability, and then the innovation on it fell off a cliff. The brief that started this site [says why, in the person's own words](/about/brief/#memo-01): the thing users kept running into was where to keep the keys, the vault keys and the access key that lets you push, and because there was no answer everything ground to a halt. That is now solved, and the brand was always a strain ("secure graph" does not say what it does), so the work moves to sgit.ai.
## What this site keeps
- **The job:** send data from A to B, encrypted here, the server blind. The same ciphertext layout, the same envelope, the same friendly tokens, the same link grammar, so links and tokens open on either site.
- **The server:** the SG/Send API, at `send.sgraph.ai` or wherever you point [Settings](/settings/). Nothing server-side changed for this site.
- **The access gate:** uploading still needs an access token during the beta; [the commercial model](/use/pricing/) says how that changes.
## What it adds
- **Keys that are kept.** Every key this site makes goes into [the keyring](/keys/) on the device, with a kind, exportable.
- **Files in vaults.** A file can go into a vault instead of a one-shot transfer: versioned, updatable, browsable, clonable with sgit, shared read-only with a key that cannot write.
- **QR codes first.** Every share is drawn as a code; the long-key hand-over that broke the flow is optional.
- **The code as a release of its own.** [api.send.sgit.ai](https://api.send.sgit.ai) holds the modules, versioned and never edited, so the site is the usage and anyone can embed the same code.
## What it does not carry yet
Counted from send.sgraph.ai's own reality file at v0.25 and its UI at v0.3.x on 20 October 2026, and listed as proposed in [this site's reality file](/about/reality/): folder transfers, text and secret transfers, uploads over 4 MB through presigned multipart, the seventeen locales, the share zip of a whole vault behind a token, the gallery and viewers, the admin console, the data rooms. Some of it will come as releases of the API; some of it belongs to the vault browser at [vault.sgraph.ai](https://vault.sgraph.ai) and will stay there.
==============================================================================
# QR codes and friendly tokens
> Why the link is drawn as a QR code, what the code carries and does not, and the trade a friendly token makes against a random key.
*Source: · send.sgit.ai v0.1.2 · this file is generated from the same content as the page, so the two cannot drift. Every page on this site has a `.md` twin; internal links below point at pages, swap `.html` for `.md` to read the twin.*
---
# QR codes and friendly tokens
## The QR code is the link
Every share on this site comes with a QR code, drawn in your browser by the pinned release's QR module from the link itself. Nothing is sent to make it; it is an SVG of the same characters you can copy. A phone's camera opens the link, and the key in the fragment reaches the phone's browser and no server.
That makes the QR code the first way to hand a link over when the two people are in the same room, on a call with a screen, or when one of them is on a phone and the other is not. It replaces the step that broke most hand-overs before: reading out or pasting a long key. The code carries everything the link carries, so it is as secret as the link: do not put it on a slide you will publish.
## A friendly token fits in a smaller square
`river-cloud-3847` is sixteen characters where a link with a random key is ninety. The QR code is smaller and scans from further away, and the token can also be said aloud or typed. The transfer id and the key are both derived from the token in both browsers, so the server never maps a token to anything and never sees it.
The trade: there are 1,024,000,000 tokens, and anyone holding the ciphertext can try them offline at 600,000 PBKDF2 rounds each. A random 256-bit key cannot be tried. So a friendly token is for a link that expires, a file that is not worth that effort, and a moment when speaking it is the point; a random key is for everything else. The send page shows which you chose and the expiry you set.
## Scanning
This release draws codes; it does not scan them. A phone's camera app opens a scanned link in the browser, which is the common case. Scanning with the page's own camera is proposed and listed as such in [the reality file](/about/reality/).
## Compatibility
A link or a token made here opens on [send.sgraph.ai](https://send.sgraph.ai), and one made there opens on [the open page](/open/) here: the fragment grammar, the token derivations and the word list are the same, copied from the SG/Send repository and held by tests. [The contracts](https://api.send.sgit.ai/docs/contracts/) are written down on the API's site.
==============================================================================
# Security, what the server sees
> What the server can see, what it cannot, the two secrets that must not be confused, what a friendly token costs, and what this site does not claim.
*Source: · send.sgit.ai v0.1.2 · this file is generated from the same content as the page, so the two cannot drift. Every page on this site has a `.md` twin; internal links below point at pages, swap `.html` for `.md` to read the twin.*
---
# Security: what the server sees, and what it cannot
## The server
| It can see | It cannot see |
|---|---|
| The ciphertext, and its size (the plaintext plus 28 bytes for a transfer) | The plaintext |
| When it was uploaded, and how many times it was downloaded | The file name: it is inside the ciphertext |
| A hash of the sender's IP, salted daily | The decryption key: it is in the link's fragment |
| The `content_type_hint` the sender chose | The vault key or the passphrase; it stores a hash of the write key and compares |
| Your access token, hashed, to decide whether you may upload | Who you sent the link to |
The server is a capability-checked ciphertext store: every access decision it makes is a hash comparison, and it never holds a raw key. A full compromise of it yields ciphertext and hashes. That property is the whole product rather than a feature of it, and [sgit.ai's security page](https://sgit.ai/security/) covers it from the server's side.
## This site
This site is static files on GitHub Pages: it has no way to receive a request body. The code the pages run comes from [api.send.sgit.ai](https://api.send.sgit.ai), pinned to one release whose every file is hashed in [the manifest](https://api.send.sgit.ai/v0.1.1/manifest.json) and checked by this repository's gate. No script, style or font is loaded from any other origin. Nothing is stored except what you can see on [Keys](/keys/) and the theme you picked.
## Two secrets that must not be confused
The **access token** says who may upload. It goes in a request header to the server you chose and nowhere else: never a URL, never a log. The **decryption key** says who may read. It goes in the link after `#` or by a second channel, and never reaches any server. They are unrelated values. Confusing them does not throw an error, which is why it is the first thing on [the quick start](https://api.send.sgit.ai/start/).
## What a friendly token costs
A friendly token is two words from a list of 320 and four digits: 1,024,000,000 possibilities. Anyone holding the ciphertext can try them offline, at 600,000 PBKDF2 rounds each. That is a real cost, and it is not the cost of a random 256-bit key. A friendly token is for a link that expires and a file that is not worth that effort; a random key is for the rest. The send page says which you chose.
## The keyring
The keyring on [Keys](/keys/) is plaintext in your browser's storage. It makes the keys findable, which is what was missing before; it does not make them safe from someone with your device. Export it to a password manager for the keys that matter. [Vaults and keys](/learn/vaults-and-keys/) says where each kind of key should live.
## What this site does not claim
- **Not proved against the hosted server yet.** The formats match send.sgraph.ai's published contracts and the code is tested against an in-memory implementation of its API; a round trip against `send.sgraph.ai` itself is marked proposed in [the reality file](/about/reality/) until it is recorded.
- **Not audited.** The crypto is the browser's Web Crypto API, used the same way send.sgraph.ai has since its first version; nobody outside the project has reviewed this site's use of it.
- **Not metadata-free.** Sizes, timing and counts are visible to the server, and the link is as private as the channel it travels by.
- **A beta.** Do not upload confidential or illegal content.
==============================================================================
# Vaults and keys
> What a vault is, the one secret and the keys derived from it, which may be shared and which never, where each kind of key should live, and what to do when one is lost.
*Source: · send.sgit.ai v0.1.2 · this file is generated from the same content as the page, so the two cannot drift. Every page on this site has a `.md` twin; internal links below point at pages, swap `.html` for `.md` to read the twin.*
---
# Vaults and keys
## What a vault is
A vault is a folder of files, encrypted in your browser, versioned like git: every change is a commit, the history is kept, two devices can work on it and merge, and a laptop can `sgit clone` it. send.sgraph.ai had transfers; what it did not have, and what stopped people, was a place to keep the vault keys and a way to put files into vaults from the page. This site has both.
## One secret, and the keys derived from it
| Key | What it carries | Looks like | May be shared |
|---|---|---|---|
| **The vault key** | read and write | `sgit_private_vault_:` | **never**: not in a link, a page, a chat, a repository |
| **The read key** | read only, every file, every version | `sgit_public_read_<64 hex>:` | yes: this is what a share link carries |
| **The write key** | what the server checks before accepting a push | never shown; derived from the passphrase, sent as a header, stored as a hash | no |
The read key is derived from the vault key one way, so a read key can never be turned back into write access. The vault id after the colon is the address, and it is public. [sgit.ai's credentials page](https://sgit.ai/docs/credentials.html) has the prefixes and why the word in them matters.
## Where each kind of key should live
| Key | Today, on this site | The better home |
|---|---|---|
| Vault keys | [Keys](/keys/), plaintext, per device; export to move | a password manager; [secrets.sgit.ai](https://secrets.sgit.ai)'s passkey-unlocked keyring when it ships; a registry vault fed over an append lane, as [sgit.ai's key management page](https://sgit.ai/docs/key-management.html) describes |
| Read keys | Keys, and in the links you hand out | anywhere; they are publishable |
| Transfer keys | Keys, with the delete secret | the same; they expire with the transfer |
| Access tokens | Keys, per server | a password manager |
## When a key is lost
There is no reset. A vault whose vault key is lost cannot be written to again; if a read key survives it can still be read and cloned, and its contents copied into a new vault. A transfer whose key is lost is gone. This is the price of the server never holding a key, and it is why the keyring exists: a key that is written down somewhere is a key that is not lost.
## When a key leaks
A read key that leaks means the vault's contents are as public as wherever it went; revocation is not retroactive, because anyone who fetched the objects keeps them. A vault key that leaks means rotating: make a new vault, copy the files, re-share the new read key, and stop using the old one. [Keys](/keys/) can revoke a transfer, which deletes it on the server, if the transfer was sent from this device.
## sgit, on a laptop
```
pip install sgit-ai
sgit clone sgit_public_read_…:vaultid # read-only, every file and every commit
sgit clone sgit_private_vault_…:vaultid # read and write
sgit commit "added the report" && sgit push # then open it here again: the browser and the CLI are two clones of one vault
```
[sgit.ai](https://sgit.ai) is the documentation for the CLI and the vault format.
==============================================================================
# Open a link
> Open a transfer link, a friendly token, or a vault's read key. Everything after the # stays in your browser; decryption happens here, and opening needs no account and no token.
*Source: · send.sgit.ai v0.1.2 · this file is generated from the same content as the page, so the two cannot drift. Every page on this site has a `.md` twin; internal links below point at pages, swap `.html` for `.md` to read the twin.*
---
# Open
Everything that unlocks a file is after the `#` in the link, which your browser never sends to any server. Paste a link, a friendly token, or a read key; the file is decrypted here.
A link, a token, or a key
Open Nothing you paste here is uploaded.
## What this page can open
Looks likeIt isWhat happens
`#abc123def456/`43 charactersa transfer with its keydownloaded, decrypted here, saved with the name that was inside the ciphertext
`#abc123def456`a transfer, link onlythis page asks for the key that travelled separately
`#river-cloud-3847`a friendly tokenthe transfer id and the key are both derived from the token, here
`#sgit_public_read_…:vaultid`a vault's read keyevery file and every version, read only, decrypted here; also `sgit clone`-able
`#sgit_private_vault_…:vaultid`a vault keyopens too, with a warning: it is write access and should not have travelled in a link
A link made on [send.sgraph.ai](https://send.sgraph.ai) opens here too, and the other way round: the formats are the same. [QR codes and friendly tokens](/learn/qr-codes/).
==============================================================================
# Settings
> Which SG/Send server this browser talks to, the access token for it, and which copy of the API the pages load. All of it stays in this browser.
*Source: · send.sgit.ai v0.1.2 · this file is generated from the same content as the page, so the two cannot drift. Every page on this site has a `.md` twin; internal links below point at pages, swap `.html` for `.md` to read the twin.*
---
# Settings
The server
The SG/Send API host that stores ciphertext. The hosted one is `send.sgraph.ai`; [you can run your own](https://sgit.ai/deploy/), or [one on this machine](/use/#local) for trying things out.
Host
Access token for that server
Sent as a request header to that host only, never in a URL, kept in [your keys](/keys/). This is the beta gate: [how to get one](/use/pricing/).
Save and check
## The code these pages run
Pinned releaseLoaded
Load the API from another copy (this browser only)
For developers: a local checkout of [api.send.sgit.ai](https://api.send.sgit.ai) served at a URL ending in the release directory, for example `http://localhost:8788/v0.1.1`. Other readers are not affected.
==============================================================================
# Examples, a page, curl, Python
> The same transfer made three ways: from a page with the pinned API, from a shell with curl and openssl, and from Python for an agent; plus the server in memory for trying it on a laptop.
*Source: · send.sgit.ai v0.1.2 · this file is generated from the same content as the page, so the two cannot drift. Every page on this site has a `.md` twin; internal links below point at pages, swap `.html` for `.md` to read the twin.*
---
# Use it: examples
Everything here talks to the same server with the same formats, so a file sent one way opens every other way, including on [the open page](/open/).
## From a page {#page}
```html
```
Full walk-through, including a friendly token and a vault: [the quick start](https://api.send.sgit.ai/start/).
## From a shell, with curl and openssl {#curl}
The layout is simple enough to do by hand: envelope, encrypt, three calls.
```bash
TOKEN=...; HOST=https://send.sgraph.ai; FILE=report.pdf
KEY=$(openssl rand -hex 32); IV=$(openssl rand -hex 12)
META=$(printf '{"filename":"%s"}' "$FILE"); LEN=$(printf '%s' "$META" | wc -c)
{ printf 'SGMETA\0'; printf "$(printf '\\x%02x\\x%02x\\x%02x\\x%02x' $((LEN>>24&255)) $((LEN>>16&255)) $((LEN>>8&255)) $((LEN&255)))"; printf '%s' "$META"; cat "$FILE"; } > plain.bin
# AES-256-GCM: openssl's CLI cannot emit the GCM tag; use the Python example below for GCM, or sgit's transfer command when it ships.
```
A GCM tag is required, and OpenSSL's command line does not produce one, so the honest shell example stops here: the three HTTP calls are below in Python, and they are the same from curl.
```bash
ID=$(curl -s -H "x-sgraph-access-token: $TOKEN" -H 'content-type: application/json' -d '{"file_size_bytes":1234,"content_type_hint":"application/octet-stream"}' $HOST/api/transfers/create | python3 -c 'import json,sys;print(json.load(sys.stdin)["transfer_id"])')
curl -s -H "x-sgraph-access-token: $TOKEN" -H 'content-type: application/octet-stream' --data-binary @cipher.bin $HOST/api/transfers/upload/$ID
curl -s -X POST -H "x-sgraph-access-token: $TOKEN" $HOST/api/transfers/complete/$ID
echo "https://send.sgit.ai/open/#$ID/$KEY_BASE64URL"
```
## From Python, for an agent {#python}
An agent that finishes a job and hands the result over once. Standard library plus `cryptography`; no account for the recipient.
```python
import base64, json, os, struct, urllib.request
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
HOST, TOKEN = 'https://send.sgraph.ai', os.environ['SGRAPH_ACCESS_TOKEN'] # the token: an env var, a header, never a URL
def send_file(path, expires_ms=0, max_downloads=0):
data = open(path, 'rb').read()
meta = json.dumps({'filename': os.path.basename(path)}).encode()
plain = b'SGMETA\0' + struct.pack('>I', len(meta)) + meta + data # the name inside the ciphertext
key, iv = AESGCM.generate_key(256), os.urandom(12)
cipher = iv + AESGCM(key).encrypt(iv, plain, None) # IV || ciphertext || tag
def call(method, p, body=None, ctype='application/json'):
req = urllib.request.Request(HOST + p, data=body, method=method, headers={'x-sgraph-access-token': TOKEN, 'content-type': ctype})
with urllib.request.urlopen(req) as r: return r.read()
tid = json.loads(call('POST', '/api/transfers/create', json.dumps({'file_size_bytes': len(data), 'content_type_hint': 'application/octet-stream', 'max_downloads': max_downloads, 'expires_at': expires_ms}).encode()))['transfer_id']
call('POST', f'/api/transfers/upload/{tid}', cipher, 'application/octet-stream')
call('POST', f'/api/transfers/complete/{tid}')
k = base64.urlsafe_b64encode(key).decode().rstrip('=')
return f'https://send.sgit.ai/open/#{tid}/{k}' # the key: in the fragment, never logged
def receive(link):
frag = link.split('#', 1)[1].split('|')[0]; tid, k = frag.split('/', 1)
key = base64.urlsafe_b64decode(k + '=' * (-len(k) % 4))
with urllib.request.urlopen(f'{HOST}/api/transfers/download/{tid}') as r: cipher = r.read() # public: the key is the gate
plain = AESGCM(key).decrypt(cipher[:12], cipher[12:], None)
assert plain[:7] == b'SGMETA\0'; n = struct.unpack('>I', plain[7:11])[0]
return json.loads(plain[11:11 + n])['filename'], plain[11 + n:]
```
For an agent-facing link prefer `max_downloads=0` with a short `expires_ms`: a retry is not a reader, and a cap burns the allowance. [For agents](/use/agents/) has the rest of that guidance.
## On a laptop, with the server in memory {#local}
```
git clone https://github.com/SGit-AI/SGit-AI__Website__Send__API
node SGit-AI__Website__Send__API/releases/v0.1.1/tests/server.mjs 8787 local-dev-token
```
Then in [Settings](/settings/) choose "a server on this machine" with the token `local-dev-token`. Every feature works, nothing leaves the machine, and it forgets everything when it stops. It is the same server the API's 43 tests run against.
==============================================================================
# For agents
> How an agent sends a result to a person or to another agent with these formats, what to put in the bundle, which secrets go where, and the pages to read first.
*Source: · send.sgit.ai v0.1.2 · this file is generated from the same content as the page, so the two cannot drift. Every page on this site has a `.md` twin; internal links below point at pages, swap `.html` for `.md` to read the twin.*
---
# For agents
You are reading the page for agents of send.sgit.ai. Every page here has a markdown twin at the same path with `.md` instead of `.html`; [`/llms.txt`](/llms.txt) lists them, and [`/llms-full.txt`](/llms-full.txt) is all of them in one request. The code this site runs has [its own agents page](https://api.send.sgit.ai/agents/).
## Handing a result over, once
A transfer is the right shape when a job finishes and the result goes to someone once: a report, a bundle, a dated export. [The Python example](/use/#python) is the whole thing in forty lines; the formats are [the contracts](https://api.send.sgit.ai/docs/contracts/). Three rules, from [sgit.ai's transfer page](https://sgit.ai/api/transfers.html):
- **The access token is a header, from an environment variable or a secret store.** Never in a URL, a log line, or a transcript.
- **The decryption key is in the link, and nowhere else.** Do not persist it in node output or a tool result that is kept.
- **Prefer a time bound to a download cap** for a link another agent will open: `max_downloads: 0` with a short `expires_at`, because a retry is not a reader.
Bundle for a reader who is an agent: a `manifest.json` saying what each file is and an `llms.txt` cost nothing and are the difference between a payload that can be used and one that has to be opened by a person first.
## Working in a vault, repeatedly
A vault is the right shape when the thing is read repeatedly, updated, or browsed: use `sgit` ([the skill is on sgit.ai](https://sgit.ai/skills/)) with the vault key you were given, commit, push, and hand the **read key** to whoever should see it. Never paste a vault key into a chat; [sgit.ai's key management page](https://sgit.ai/docs/key-management.html) has the flow that sends one to a registry sealed to its public key instead.
## From a browser agent
The pinned release runs in any page: `import('https://api.send.sgit.ai/v0.1.1/send/send-api.js')`, then `SendTransfers.send()` and `receive()`, or the `vault` namespace. Opening needs no token.
## What to read first
1. [The reality file](/about/reality/): what exists on this site. If it is not there, it does not exist.
2. [Security: what the server sees](/learn/security/).
3. [The API's agents page](https://api.send.sgit.ai/agents/) and [its reality file](https://api.send.sgit.ai/about/reality/).
==============================================================================
# Embed it in your site
> Put a send box, an open page, or a QR hand-over on your own site by pinning the same release this site runs; what to pin, what to check, what stays on your origin.
*Source: · send.sgit.ai v0.1.2 · this file is generated from the same content as the page, so the two cannot drift. Every page on this site has a `.md` twin; internal links below point at pages, swap `.html` for `.md` to read the twin.*
---
# Embed it in your site
The code this site runs is not this site's. It is [api.send.sgit.ai](https://api.send.sgit.ai) v0.1.1, and any page on any origin can import it the same way:
```html
```
A script loaded from that host runs on **your** page's origin, so the keyring, the clone branch and everything the modules store stay in your site's storage; the API host has no way to receive anything. The three things to get right:
1. **Pin the release** in one file and copy its [manifest](https://api.send.sgit.ai/v0.1.1/manifest.json) beside it; make your build refuse a reference to the host that is not that release. This site does it in `tools/api.json` and `tools/check.py`.
2. **Keep the access token out of the page.** It belongs to whoever uploads, in their browser, pasted once into something like [Settings](/settings/). A token in page source is a token everyone has.
3. **Build the link on your open page.** `send.link.transferLink({ openUrl: 'https://your.site/open/', ... })`, and parse it there with `send.link.parseFragment(location.hash)`. Or point at `https://send.sgit.ai/open/`, which opens anything made with these formats.
This site's own app modules (`assets/app/send.js`, `open.js`, `vaults.js`, `keys.js`, `settings.js`) are small, plain ES modules with no framework; copy the ones you want from [the repository](https://github.com/SGit-AI/SGit-AI__Website__Send) and keep the import of the pinned release. [For developers](https://api.send.sgit.ai/for-developers/) on the API's site has the per-module notes and what runs in Node.
==============================================================================
# The commercial model
> How using this site and its capabilities is meant to be paid for, what is true today (a beta behind access tokens), what is proposed, and what will never be charged for.
*Source: · send.sgit.ai v0.1.2 · this file is generated from the same content as the page, so the two cannot drift. Every page on this site has a `.md` twin; internal links below point at pages, swap `.html` for `.md` to read the twin.*
---
# The commercial model
The brief for this site [says it plainly](/about/brief/#memo-02): the point is a full usage-based commercial model for using the site and its capabilities. This page is that model, with the status of every part marked, because most of it is not built yet.
## Today, counted {#today}
| | Status |
|---|---|
| **Opening a link** is free, needs no account and no token, and always will. The key is the gate | shipped |
| **Sending** needs an access token, issued by hand during the beta. A token has a use limit and can be revoked | shipped (the gate exists on the server; tokens are made by a person) |
| **How to get a token:** write to the address at the bottom of this page with what you want to send and how often | shipped, by email |
| **Running your own server** with the open-source SG/Send API, and pointing [Settings](/settings/) at it: no token from us, no bill from us | shipped |
| **Embedding the code** from api.send.sgit.ai in your own site: free, Apache-2.0 | shipped |
## Proposed {#proposed}
Each row is described in a brief and has no code behind it on this site. The reality file lists them as proposed; nothing here is a promise.
| Idea | Shape |
|---|---|
| **Self-service tokens** | pay for an allowance of uploads or bytes, get a token in the browser, keep it in [Keys](/keys/) |
| **Usage meter on the page** | the token's remaining uses shown on the send page, as the API already reports them |
| **Vault hosting** | a vault above a size or an age carries a cost, paid by its owner, with the read key free to everyone who holds it |
| **Organisations** | a token per team with its own servers or its own bucket, under their own keys |
| **A reading meter for shared content** | the newsroom's [SG Meter](https://api.newsroom.sgit.ai) pattern applied to a vault page: pay by how far you read, in the browser |
## What will not be charged for {#never}
- Opening a link, ever. The recipient did not choose this site.
- Reading a vault with its read key, or cloning it with sgit.
- Exporting your keys, or leaving: there is no account to close and nothing of yours on this site.
- The code: api.send.sgit.ai is open source and stays so.
## How to get an access token today
Write to [agent@riskmandate.ai](mailto:agent@riskmandate.ai) with what you want to send and how often. During the beta tokens are issued by hand and use-limited; a token is tied to a server, kept in your browser, and sent only in a request header to that server.
==============================================================================
# Vaults
> The vaults this browser holds keys for. Create one, add files as commits, see the history, and share it read-only with a link and a QR code; clone it anywhere with sgit.
*Source: · send.sgit.ai v0.1.2 · this file is generated from the same content as the page, so the two cannot drift. Every page on this site has a `.md` twin; internal links below point at pages, swap `.html` for `.md` to read the twin.*
---
# Vaults
A vault is a folder of files, encrypted here, versioned like git, that you can open again, add to, and share read-only. The vault key stays on this device; the read key is the one you hand out. Anyone with the read key can also `sgit clone` it on a laptop.
**Beta:** creating and writing to a vault needs an access token; [set one in Settings](/settings/). Opening a read key needs nothing.
## On this device
Create a vault
Create
## How a vault differs from a transfer
TransferVault
Shapeone file, uploaded oncea versioned tree of files
Historynone; there is no second versioncommits, with messages
The reader getsthe whole file, or nothingany single file, without the rest
Lifecycleexpires, caps downloads, can be revokedlives until deleted
The credentiala key in the linka read key, derived one way from the vault key
Reach for it whena thing is handed over oncea thing is read repeatedly, updated, or browsed
[Vaults and keys](/learn/vaults-and-keys/), in full.
==============================================================================
# Version history
> One line per version, newest first, saying what changed and why. Every change that lands on dev is a version; the deploy tags it.
*Source: · send.sgit.ai v0.1.2 · this file is generated from the same content as the page, so the two cannot drift. Every page on this site has a `.md` twin; internal links below point at pages, swap `.html` for `.md` to read the twin.*
---
# Version history
Every change that lands on `dev` is a version, in `tools/version.json`, tagged by the deploy and shown in the header of every page. The code the app runs has [a history of its own](https://api.send.sgit.ai/versions/).
| Version | Date | Kind | What changed, and why |
|---|---|---|---|
| **v0.1.2** | 2026-10-20 | fix | **the pin check leaves articles alone.** v0.1.1 landed with the gate red on one line: the agent's article about the first release names the v0.1.0 address it was written against, and the pin check read that as an unpinned reference. An article is the record of its day, so the check now skips /articles/; nothing a page runs changed. Recorded here rather than hidden, as the release discipline asks. |
| **v0.1.1** | 2026-10-20 | fix | **the site pins api.send.sgit.ai v0.1.1, whose health check asks the route the hosted service serves.** After the first deploy, Settings reported send.sgraph.ai as not answering: the v0.1.0 release asked /api/health, which the hosted service does not serve (its route is /api/info/health). The API's v0.1.1 fixes that; this version changes the pin and copies its manifest, and nothing else on the site. The same run measured that send.sgraph.ai allows requests from this origin with every header the release sends. |
| **v0.1.0** | 2026-10-20 | release | **the first version of send.sgit.ai: send, open, vaults, keys and settings on the pinned API, with the explanations, the examples, the commercial model and three articles.** From the four voice memos of 20 October 2026, published in full with their corrections. The app runs api.send.sgit.ai v0.1.0, pinned with its manifest: a file sent as a transfer or into a vault, a link, a friendly token or a QR code to hand over, an open page for any of them, vaults created and shared read-only, and a keyring on the device. An end-to-end browser test drives all of it against the in-memory server. What is not built is listed as proposed in the reality file, including the round trip against the hosted send.sgraph.ai. |