mirror of
https://github.com/profullstack/logicsrc.git
synced 2026-10-02 20:57:03 +00:00
feat(ans): implement @logicsrc/ans M1 — resolver + offline verifier
M1 of the ANS SDK (docs/ans-sdk.md): - name: parse/format ans://v<semver>.<agent>.<domain> - cbor: minimal RFC 8949 codec for the COSE_Sign1 subset - verify/merkle: RFC 6962 leaf/node hashing, tree build, inclusion-proof generation + verification - verify/es256 + cose: COSE_Sign1 build/parse, Sig_structure, ES256 (WebCrypto) - verify/rootkeys: kid -> verifier key (JWKS entries; sumdb-note is M2) - verify: verifyReceipt() + verifyResolution() (signature + inclusion proof + name binding), pure and offline - client: AnsClient resolve/rootKeys/register/status over injectable fetch, with a DnsApplier hook for verify-dns Tests (24) cover name parsing, CBOR round-trips/vectors, RFC 6962 proofs, a full ES256+Merkle receipt round-trip with positive/negative cases, and the client against mocked fetch. Wired into the root build script. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
0ae24719e3
commit
29975b2df7
20 changed files with 1009 additions and 28 deletions
34
packages/ans/src/name.test.ts
Normal file
34
packages/ans/src/name.test.ts
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
import { describe, expect, it } from 'vitest';
|
||||
import { formatAnsName, parseAnsName } from './name.js';
|
||||
|
||||
describe('parseAnsName', () => {
|
||||
it('parses a well-formed ans:// name', () => {
|
||||
expect(parseAnsName('ans://v1.0.0.my-agent.example.com')).toEqual({
|
||||
raw: 'ans://v1.0.0.my-agent.example.com',
|
||||
version: '1.0.0',
|
||||
agent: 'my-agent',
|
||||
domain: 'example.com',
|
||||
});
|
||||
});
|
||||
|
||||
it('parses multi-label domains and prerelease versions', () => {
|
||||
const parsed = parseAnsName('ans://v2.3.1-beta.bot.agents.example.co.uk');
|
||||
expect(parsed.version).toBe('2.3.1-beta');
|
||||
expect(parsed.agent).toBe('bot');
|
||||
expect(parsed.domain).toBe('agents.example.co.uk');
|
||||
});
|
||||
|
||||
it.each([
|
||||
'https://v1.0.0.a.example.com',
|
||||
'ans://1.0.0.a.example.com',
|
||||
'ans://v1.0.a.example.com',
|
||||
'ans://v1.0.0.bad agent.example.com',
|
||||
'ans://v1.0.0.agent',
|
||||
])('rejects malformed name %s', (raw) => {
|
||||
expect(() => parseAnsName(raw)).toThrow();
|
||||
});
|
||||
|
||||
it('round-trips through formatAnsName', () => {
|
||||
expect(formatAnsName({ version: '1.2.3', agent: 'a', domain: 'example.com' })).toBe('ans://v1.2.3.a.example.com');
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue