@muretai/agent-entry 1.6.1 → 1.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +36 -17
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -104,14 +104,17 @@ answers questions and hands off nothing, is a signed claim you cannot keep.
104
104
  | option | default | what it does |
105
105
  |---|---|---|
106
106
  | `skills` | `[]` | the menu above — what a visitor learns before knocking |
107
- | `openDoor` | `true` | publishes `muretai.open_door`: the field that tells a visiting agent it may message you with no introduction |
107
+ | `openDoor` | `true` | publishes `agentEntry.open_door`: the field that tells a visiting agent it may message you with no introduction. The same fact is emitted under the older `muretai.open_door` spelling beside it — read either, write the neutral one |
108
108
  | `anonymousLane` | `false` | also answer **unsigned** inquiries. They create no account row, and the lane is capped entry-wide — an unauthenticated caller must never become an unmetered signing oracle |
109
- | `anonRatePerMin` | `30` | anonymous replies per minute, entry-wide. Signed senders are not bound by it: they are attributable and already in your ledger |
109
+ | `anonRatePerMin` | `30` | anonymous replies per minute, entry-wide |
110
+ | `signedRatePerMin` | `60` | signed replies per minute **per account**, ON by default. Attribution is not scarcity: a `did:key` costs nothing to mint, so being in your ledger was never a bound |
111
+ | `signedRatePerMinTotal` | `600` | signed replies per minute for the **whole entry**. Free identity defeats per-identity metering by definition, so only the aggregate resists a flood |
112
+ | `guest` | `false` | put the door on a path of its own and leave `GET /` alone entirely — for a site that is keeping its front page. A `GET` on a guest mount answers **405 with `Allow: POST, OPTIONS`**, never 404: the address is signed into a public card, and hiding a published address conceals nothing |
110
113
  | `maxAccounts` | `50000` | how many accounts the in-process ledger holds |
111
114
  | `domains` | none | the domains this entry speaks for (see below) |
112
115
  | `basePath` | from `baseUrl` | the path this entry answers at, derived rather than set beside it |
113
116
  | `wbaVerifiers` | none | a JWKS document (`{"keys":[…]}`) of Ed25519 keys whose holders this entry should **recognise** on inbound signed requests (Web Bot Auth / RFC 9421 — see *Who is knocking*). Recognition only adds `env.wba_did` and a visit count; it never changes a verdict |
114
- | `observer` | none | called once per message with the same envelope your responder gets, **after** the verdict — for counting, logging, analytics. It cannot matter: its return is discarded, a throw is swallowed, a promise is never awaited, so a slow or broken watcher cannot delay or change one byte of the signed reply. See [Counting visits](#counting-visits-without-handing-over-who-they-are) |
117
+ | `observer` | none | called once per message with the same envelope your responder gets, **after** the verdict — for counting, logging, analytics. It cannot matter: its return is discarded, a throw is swallowed, a promise is never awaited, so a slow or broken watcher cannot delay or change one byte of the signed reply. See [Counting visits](#counting-visits-without-handing-over-your-customer-list) |
115
118
  | `howToUrl` | none | a page a keyless visitor is pointed at as a worked example. **Empty means omitted** — the refusal already teaches the whole recipe without it, and a reference implementation must not stamp somebody else's docs host into every door built from it. Only set it to a URL you operate, and only after checking it resolves |
116
119
  | `name`, `description`, `version` | — | the card's own words. `description` is the line a person reads in a directory listing — and the right place to say what you record about visitors, since it is fetched **before** the knock |
117
120
 
@@ -498,8 +501,10 @@ navigator.modelContext.registerTool({
498
501
  ```
499
502
 
500
503
  `MY_DID` is the DID your Agent Entry prints at startup — **the same one**, from the same seed.
501
- That is the only rule when running both: a mismatch trips the visitor's impersonation guard,
502
- which is what it is there for.
504
+ That is the only rule when running both, and **nothing here enforces it** this package never
505
+ sees your in-page handoff. A mismatch is a site publishing two different identities for one
506
+ origin, which a careful visitor may notice and a careless one will not, so treat it as your
507
+ invariant to keep rather than a guard you are behind.
503
508
 
504
509
  What the shop gets out of it: the moment that signed message arrives, an account exists. No
505
510
  signup form, no password, nothing to reset — the sender's key is the account. Come back
@@ -529,8 +534,8 @@ and it is not one. It is the upgrade path:
529
534
  ledger back to gate, greet or rate-limit, so a fire-and-forget sink records visiting
530
535
  agents with no database anywhere. Use `observer` for it, never your responder: watching
531
536
  a visit should not be an edit to the code that decides what to say. See
532
- [Counting visits](#counting-visits-without-handing-over-who-they-are) below for the
533
- whole pattern, including the one rule that shapes it — **a DID is not a page view**,
537
+ [Counting visits](#counting-visits-without-handing-over-your-customer-list) below for the
538
+ whole pattern, including the one rule that shapes it — **a DID is not a cookie**,
534
539
  so what leaves your box is a salted digest, never the identifier itself. A sink cannot
535
540
  be read back during a request: it counts customers, it cannot recognise one. It
536
541
  replaces a log line, not the store above — none of the recommended features stand
@@ -560,7 +565,7 @@ What the entry now handles for you at the HTTP layer, so you do not have to:
560
565
  which says a server must accept the absolute form: this endpoint answers exactly the
561
566
  address its card names, and the refusal says so.
562
567
 
563
- ## Counting visits without handing over who they are
568
+ ## Counting visits without handing over your customer list
564
569
 
565
570
  You will want to know how many agents knocked, how many came back, and what they asked. All
566
571
  three are answerable — and how you answer them decides whether you are counting your visitors
@@ -571,11 +576,18 @@ envelope, after the verdict, so watching a visit stops being an edit to the code
571
576
  what to say. It cannot matter: its return is discarded, a throw is swallowed, a promise is
572
577
  never awaited — a slow or broken watcher cannot delay or change one byte of the signed reply.
573
578
 
574
- **The rule that shapes everything else: a DID is not a page view.** A visitor hands you one in
575
- order to transact with **you**, and here first contact *is* the account there is no signup
576
- form where they agreed to anything else. Forwarding the raw value to an analytics vendor shares
577
- a durable identifier its owner never offered them, silently, on a surface with no consent
578
- dialog and no visitor who could decline. So split it:
579
+ **The rule that shapes everything else: a DID is not a cookie, and it is not a throwaway
580
+ either.** Nobody imposed it the visitor read your card *before* knocking, and an owner who
581
+ wanted this conversation kept apart would have sent a different agent, because an owner runs
582
+ several and each is a distinct agent with its own lasting identity. But the one that did knock
583
+ means to keep the key it used: that is how it gets recognised, introduced and trusted anywhere on
584
+ the network, so it is closer to a professional's name than to a tracking cookie.
585
+
586
+ Which is exactly why the raw value should not travel onward. **The DID is genuinely durable, and
587
+ you were given it so that YOU could reach them again.** Widen that purpose and nothing happens to
588
+ you legally, which is the part worth understanding: the owner simply stops sending that agent to
589
+ you. Silently, at no cost, and you never learn you lost them — not one data point, the whole
590
+ relationship. So split it:
579
591
 
580
592
  - **What leaves** — a salted digest and a few shape facts. Never the DID, never the text.
581
593
  - **What stays** — the relationship (who, how many, first and last seen) in your own store,
@@ -642,7 +654,7 @@ in the same breath, in plain words.
642
654
 
643
655
  This module is not alone. A Python reference implements the same contract, and the two are
644
656
  held to **identical verdicts** by an acceptance suite: it runs the same attack battery
645
- against both, drives this module against `testdata/wire_vectors.json` byte for byte, posts
657
+ against both, drives this module against the same wire vectors byte for byte, posts
646
658
  identical bytes to each over real sockets — down to the HTTP framing — and requires the same
647
659
  status, the same account outcome and the same signed reply from both. If you write a third
648
660
  implementation, that suite is the gate.
@@ -671,9 +683,16 @@ because a shared library would only ever have covered the parts they happen to s
671
683
  suite posts identical bytes to both, down to the HTTP framing, and requires the same status,
672
684
  the same account outcome and the same signed reply.
673
685
 
674
- `testdata/wire_vectors.json` is the part of that gate you can run here: it pins the canonical
675
- JSON, the signing payloads, the card envelopes and the did:key round-trips this module must
676
- reproduce byte for byte.
686
+ **The part of that gate you can run here ships in this package.** `npm test` executes
687
+ `conformance/run.mjs` against `conformance/vectors.json` the canonical JSON, the signing
688
+ payloads, the card envelopes and the `did:key` round-trips this module must reproduce byte
689
+ for byte. No network, no checkout of ours, nothing to ask us for:
690
+
691
+ ```bash
692
+ npm test
693
+ ```
694
+
695
+ Write a third implementation and point it at the same vectors.
677
696
 
678
697
  ## What this is part of
679
698
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@muretai/agent-entry",
3
- "version": "1.6.1",
3
+ "version": "1.6.3",
4
4
  "description": "Make your website answer AI agents: an A2A agent endpoint that verifies who is knocking, opens an account for them and replies signed, in one HTTP round trip. Zero dependencies. Pairs with llms.txt and WebMCP.",
5
5
  "type": "module",
6
6
  "main": "muretai-agent-entry.mjs",