@metacensus/api 0.2.0 → 0.4.0
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.
- package/README.md +158 -73
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/public.d.ts +1 -1
- package/dist/public.d.ts.map +1 -1
- package/dist/public.js +2 -2
- package/dist/public.js.map +1 -1
- package/dist/signing.d.ts +2 -1
- package/dist/signing.d.ts.map +1 -1
- package/dist/signing.js +1 -1
- package/dist/signing.js.map +1 -1
- package/dist/src/client.d.ts +57 -38
- package/dist/src/client.d.ts.map +1 -1
- package/dist/src/client.js +146 -79
- package/dist/src/client.js.map +1 -1
- package/dist/src/metacensus/v1/auth.d.ts +52 -8
- package/dist/src/metacensus/v1/auth.d.ts.map +1 -1
- package/dist/src/metacensus/v1/common.d.ts +77 -31
- package/dist/src/metacensus/v1/common.d.ts.map +1 -1
- package/dist/src/metacensus/v1/common.js +0 -10
- package/dist/src/metacensus/v1/common.js.map +1 -1
- package/dist/src/metacensus/v1/prop.d.ts +44 -31
- package/dist/src/metacensus/v1/prop.d.ts.map +1 -1
- package/dist/src/metacensus/v1/prop.js +18 -18
- package/dist/src/metacensus/v1/prop.js.map +1 -1
- package/dist/src/metacensus/v1/topic.d.ts +16 -13
- package/dist/src/metacensus/v1/topic.d.ts.map +1 -1
- package/dist/src/metacensus/v1/user.d.ts +15 -12
- package/dist/src/metacensus/v1/user.d.ts.map +1 -1
- package/dist/src/route-manifest.d.ts.map +1 -1
- package/dist/src/route-manifest.js +9 -8
- package/dist/src/route-manifest.js.map +1 -1
- package/dist/src/signing.d.ts +84 -17
- package/dist/src/signing.d.ts.map +1 -1
- package/dist/src/signing.js +254 -68
- package/dist/src/signing.js.map +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -4,61 +4,163 @@ TypeScript interfaces for the MetaCensus API contract — every request and
|
|
|
4
4
|
response under `/metacensus/api/v1` and `/metacensus/public`, generated from the
|
|
5
5
|
`.proto` sources that also generate the Go side.
|
|
6
6
|
|
|
7
|
-
What ships is the generated interfaces, the route manifest, `protobufPackage`,
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
what says so, and what fails the build. The signing module is inside that
|
|
11
|
-
guard rather than an exception to it.
|
|
7
|
+
What ships is the generated interfaces, the route manifest, `protobufPackage`, a
|
|
8
|
+
batteries-included client per surface, and the signing chain. How dependencies
|
|
9
|
+
are weighed is in the repository's AGENTS.md, under "Dependencies".
|
|
12
10
|
|
|
13
11
|
```bash
|
|
14
12
|
npm install @metacensus/api
|
|
15
13
|
```
|
|
16
14
|
|
|
17
15
|
```ts
|
|
18
|
-
import
|
|
19
|
-
import { routes, Client, ApiError, type Transport } from "@metacensus/api";
|
|
16
|
+
import { Client, ApiError, type Signer } from "@metacensus/api";
|
|
20
17
|
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
18
|
+
const client = new Client({ baseUrl: "https://api.example.com", signer });
|
|
19
|
+
await client.login({ email, password }); // token stored internally
|
|
20
|
+
const topic = await client.getTopic({ topicId }); // TopicRecord: { id, recorded, name, description }
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
`Client` is batteries-included: it owns its `fetch`, holds the session token
|
|
24
|
+
across `login`/`logout`, and signs writes with the `signer` you inject. It is the
|
|
25
|
+
client to reach for. Construct it with:
|
|
26
|
+
|
|
27
|
+
- `baseUrl` — the origin; the client adds `/metacensus/api/v1` and the route.
|
|
28
|
+
- `fetch?` — a `fetch` to use instead of the global, for tests or instrumentation
|
|
29
|
+
(wrap the global to add retries, a 401 policy, or logging).
|
|
30
|
+
- `signer?` — signs writes; see "Writes", below. Omit it for a read-only client.
|
|
31
|
+
- `token?` — an initial bearer token, to resume a session without logging in.
|
|
32
|
+
- `credentials?` — the fetch credentials mode; set `"include"` in a browser so
|
|
33
|
+
the `HttpOnly` refresh cookie rides `refresh()` and `logout`. See "Auth", below.
|
|
34
|
+
|
|
35
|
+
A non-2xx response throws `ApiError` (`method`, `url`, `status`, and the raw
|
|
36
|
+
`body` — parse it defensively, since a 404 or 405 comes from the router, not a
|
|
37
|
+
handler). Every scalar is required, which is what makes Go's `EmitDefaultValues`
|
|
38
|
+
and these types describe the same document: `client.createTopic({ content: { name } })`
|
|
39
|
+
does not type-check, `{ content: { name, description: "" } }` does.
|
|
40
|
+
|
|
41
|
+
## Reads: flat record or signed envelope
|
|
42
|
+
|
|
43
|
+
A read returns the **flat record** — the domain object with the server's `id`
|
|
44
|
+
and `recorded` folded in, and the `{content, userSignature}` envelope gone:
|
|
45
|
+
|
|
46
|
+
```ts
|
|
47
|
+
const topic = await client.getTopic({ topicId }); // { id, recorded, name, description }
|
|
48
|
+
topic.name; // not topic.content.name
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
The envelope isn't uniform, so the record isn't either:
|
|
52
|
+
|
|
53
|
+
| Response shape | `getX` / `listX` returns |
|
|
54
|
+
| --- | --- |
|
|
55
|
+
| id-bearing envelope (topic, prop, user) | `TopicRecord` — `{ id, recorded, ...content }` — / `TopicRecord[]` |
|
|
56
|
+
| a vote — envelope with **no `id`** | `VoteRecord` (no `id`) / `VoteRecord[]` |
|
|
57
|
+
| a member — already flat | `Member`, unchanged / `Member[]` |
|
|
58
|
+
|
|
59
|
+
When you need the signature itself — verifying authorship, comparing `recorded`
|
|
60
|
+
against the signer's `time`, or re-checking the assertion — each signed-envelope
|
|
61
|
+
read has a **`getXSigned`** twin that returns the raw envelope:
|
|
62
|
+
|
|
63
|
+
```ts
|
|
64
|
+
import { verifyUser, participantPolicy } from "@metacensus/api/signing";
|
|
65
|
+
|
|
66
|
+
const signed = await client.getTopicSigned({ topicId }); // { id, recorded, content, interpretation, userSignature }
|
|
67
|
+
const pub = await resolveEnrolledKey(signed.userSignature.keyId); // your key directory
|
|
68
|
+
await verifyUser(pub, signed.content, signed.interpretation, signed.userSignature, participantPolicy(origin));
|
|
27
69
|
```
|
|
28
70
|
|
|
29
|
-
`
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
71
|
+
`getXSigned` exists only where there's a signature to see; `Member` has none.
|
|
72
|
+
|
|
73
|
+
## Writes and the signer
|
|
74
|
+
|
|
75
|
+
A write takes **flat content** — never the envelope — and the `signer` returns
|
|
76
|
+
the record's `interpretation`, the `Signature` over it, and (sign-up only) the
|
|
77
|
+
enrolling `publicKey`; the client assembles the body. The signer is set once on
|
|
78
|
+
the constructor, because the key it signs with is identical for a session. The
|
|
79
|
+
signing mechanism is a **passkey (WebAuthn)**: the signer runs the ceremony and
|
|
80
|
+
packages its assertion — the private key never enters the client, and cannot,
|
|
81
|
+
because a passkey's key is non-extractable in the authenticator.
|
|
33
82
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
83
|
+
```ts
|
|
84
|
+
import {
|
|
85
|
+
interpretation, userChallenge, keyId, participantPolicy,
|
|
86
|
+
} from "@metacensus/api/signing";
|
|
87
|
+
|
|
88
|
+
const signer: Signer = async (content, contentType) => {
|
|
89
|
+
const interp = interpretation(contentType); // { spec, contentType } — the client names contentType
|
|
90
|
+
const kid = await keyId(publicKey);
|
|
91
|
+
const time = new Date().toISOString();
|
|
92
|
+
|
|
93
|
+
// The digest the assertion must commit to, carried as the WebAuthn challenge.
|
|
94
|
+
const challenge = await userChallenge(content, interp, kid, time);
|
|
95
|
+
const cred = await navigator.credentials.get({
|
|
96
|
+
publicKey: { challenge, allowCredentials: [/* this device's passkey */] },
|
|
97
|
+
}); // ui#55 owns provisioning and RP-ID scoping
|
|
98
|
+
|
|
99
|
+
const r = cred.response as AuthenticatorAssertionResponse;
|
|
100
|
+
return {
|
|
101
|
+
interpretation: interp,
|
|
102
|
+
signature: {
|
|
103
|
+
keyId: kid,
|
|
104
|
+
time,
|
|
105
|
+
assertion: {
|
|
106
|
+
authenticatorData: toBase64Url(r.authenticatorData),
|
|
107
|
+
clientDataJson: toBase64Url(r.clientDataJSON), // its challenge === base64url(challenge)
|
|
108
|
+
signature: toBase64Url(r.signature), // DER, verified as-is
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
};
|
|
39
113
|
|
|
40
|
-
|
|
41
|
-
|
|
114
|
+
const client = new Client({ baseUrl, signer });
|
|
115
|
+
const created = await client.createTopic({ content: { name: "A review", description: "" } });
|
|
116
|
+
// TopicRecord, flattened like a read
|
|
117
|
+
```
|
|
42
118
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
119
|
+
The client supplies `content` and the exact `contentType` (the one thing left to
|
|
120
|
+
the caller, and the easiest to get wrong); the signer builds the interpretation
|
|
121
|
+
and the assertion. A headless signer (a server or a test) builds the same shape
|
|
122
|
+
with `assert()` instead of a browser ceremony — one format, both layers. A write
|
|
123
|
+
on a client built without a signer throws. **The browser ceremony above is
|
|
124
|
+
sketch, not shipped: provisioning a passkey to a device, RP-ID scoping across
|
|
125
|
+
environments, and recovery are [ui#55](https://github.com/metacensus/ui/issues/55).**
|
|
126
|
+
|
|
127
|
+
## Auth and the session token
|
|
128
|
+
|
|
129
|
+
There are two tokens. The **access token** is short-lived: `login` and `signUp`
|
|
130
|
+
store the one they return, the client adds `Authorization: Bearer <token>` to
|
|
131
|
+
every later request, and `session.expiresIn` (seconds) says how long it lasts.
|
|
132
|
+
`token` (a getter) exposes the current one, to persist and restore a session via
|
|
133
|
+
the `token` option. `signUp` signs its `User` content through the same signer;
|
|
134
|
+
the signer returns the enrolling `publicKey`, which the client sends on the
|
|
135
|
+
request (not on the signature — no record carries its own verification key) and
|
|
136
|
+
the store binds under the signature's `keyId`. Keep the password out of
|
|
137
|
+
`content`, since content is what gets stored.
|
|
138
|
+
|
|
139
|
+
The **refresh token** is long-lived and never touches JavaScript. In a browser
|
|
140
|
+
the server keeps it in an `HttpOnly` cookie, so `refresh()` sends an empty body
|
|
141
|
+
and lets the cookie speak — construct the client with `credentials: "include"`
|
|
142
|
+
so the browser attaches that cookie (and the deployment must answer credentialed
|
|
143
|
+
CORS for your origin). `refresh()` returns a fresh `Session` and stores its new
|
|
144
|
+
access token, exactly as `login` does; the refresh token is rotated on each use
|
|
145
|
+
and `logout` revokes it. A non-browser caller with no cookie can instead pass the
|
|
146
|
+
token in `RefreshRequest.refreshToken` (and `LogoutRequest.refreshToken`) — the
|
|
147
|
+
contract is cookie-agnostic; the cookie is a transport the server adds.
|
|
148
|
+
|
|
149
|
+
The client keeps no refresh policy of its own: a 401 on an expired access token
|
|
150
|
+
is an ordinary `ApiError`, and the consumer decides when to call `refresh()` and
|
|
151
|
+
retry (react-query, say). Refresh at or before `expiresIn` to avoid the round
|
|
152
|
+
trip.
|
|
47
153
|
|
|
48
154
|
## The public surface
|
|
49
155
|
|
|
50
156
|
The public, unauthenticated surface is an entry point of its own in the same
|
|
51
|
-
package, with a client to match:
|
|
157
|
+
package, with a client to match — no signer, no token:
|
|
52
158
|
|
|
53
159
|
```ts
|
|
54
160
|
import type { PartnerSubmission } from "@metacensus/api/public";
|
|
55
|
-
import {
|
|
56
|
-
PartnerSubmission_Interest,
|
|
57
|
-
PublicClient,
|
|
58
|
-
publicPrefix,
|
|
59
|
-
} from "@metacensus/api/public";
|
|
161
|
+
import { PartnerSubmission_Interest, PublicClient } from "@metacensus/api/public";
|
|
60
162
|
|
|
61
|
-
const pub = new PublicClient(
|
|
163
|
+
const pub = new PublicClient({ baseUrl });
|
|
62
164
|
await pub.submitPartnerInterest({ name, email, interests, message, website: "" });
|
|
63
165
|
```
|
|
64
166
|
|
|
@@ -66,8 +168,6 @@ One package because the SPA calls both surfaces from one build; an entry point
|
|
|
66
168
|
per surface because a consumer of only the public surface should not acquire the
|
|
67
169
|
authenticated types. `@metacensus/api/signing` is a third, splitting by concern
|
|
68
170
|
rather than by surface — nothing on the public surface is ever signed.
|
|
69
|
-
`PublicClient` sends no credentials of its own; pass it a separate transport
|
|
70
|
-
from the one you pass `Client`.
|
|
71
171
|
|
|
72
172
|
`ApiError` is the same class from either entry point, so `instanceof ApiError`
|
|
73
173
|
holds for a failure from either surface. Importing it twice is harmless.
|
|
@@ -88,47 +188,32 @@ the enum's comment for why.
|
|
|
88
188
|
|
|
89
189
|
## Signing
|
|
90
190
|
|
|
91
|
-
Every write on the authenticated surface carries a `content` message
|
|
92
|
-
`userSignature` over
|
|
93
|
-
says who authored the record, and the API server does
|
|
94
|
-
verified by the persistence layer, behind the edge.
|
|
191
|
+
Every write on the authenticated surface carries a `content` message, an
|
|
192
|
+
`interpretation`, and a `userSignature` over both. A session token says who is
|
|
193
|
+
connected; the signature says who authored the record, and the API server does
|
|
194
|
+
not check it — it is verified by the persistence layer, behind the edge.
|
|
195
|
+
`@metacensus/api/signing` is what your `Signer` uses, and what a verifier calls:
|
|
95
196
|
|
|
96
197
|
```ts
|
|
97
|
-
import {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
const content = { name: "A review", description: "" };
|
|
102
|
-
const userSignature = {
|
|
103
|
-
signerId,
|
|
104
|
-
keyId: await keyId(publicKey),
|
|
105
|
-
alg: "Es384",
|
|
106
|
-
publicKey: "", // inline only on sign-up, which is what enrols the key
|
|
107
|
-
signingTime: new Date().toISOString(),
|
|
108
|
-
spec: SPEC,
|
|
109
|
-
contentType: "metacensus.v1.TopicContent",
|
|
110
|
-
value: "",
|
|
111
|
-
};
|
|
112
|
-
userSignature.value = await sign(privateKey, content, userSignature);
|
|
198
|
+
import {
|
|
199
|
+
SPEC, interpretation, userChallenge, assert, verifyUser,
|
|
200
|
+
authenticatorData, participantPolicy, keyId, generateKeyPair, FLAG_UP, FLAG_UV,
|
|
201
|
+
} from "@metacensus/api/signing";
|
|
113
202
|
|
|
114
|
-
|
|
203
|
+
const { privateKey, publicKey } = await generateKeyPair(); // ECDSA P-256 (ES256)
|
|
115
204
|
```
|
|
116
205
|
|
|
117
|
-
The
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
`
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
lookup rather than a guess.
|
|
129
|
-
|
|
130
|
-
The full account of the chain, and `go/signing`, the other half that has to
|
|
131
|
-
compute the same digest, are in the repository README.
|
|
206
|
+
The mechanism is **WebAuthn/passkeys**, one format for both the participant and
|
|
207
|
+
the institution (ECDSA P-256 / ES256). This module is the toolkit: `interpretation`
|
|
208
|
+
and `userChallenge` build the digest, `assert` makes a headless assertion,
|
|
209
|
+
`verifyUser`/`verifyCountersign` check one under a `participantPolicy` or
|
|
210
|
+
`institutionPolicy`. `routes` carries a `signed` flag per route, so "which routes
|
|
211
|
+
need a key?" is a lookup rather than a guess.
|
|
212
|
+
|
|
213
|
+
The scheme, the digest, and the verify procedure are the repository README's
|
|
214
|
+
"The signing chain"; `go/signing` is the other half that computes the same digest
|
|
215
|
+
and whose DER assertions this module verifies. The browser passkey ceremony
|
|
216
|
+
itself is [ui#55](https://github.com/metacensus/ui/issues/55).
|
|
132
217
|
|
|
133
218
|
## Both surfaces
|
|
134
219
|
|
package/dist/index.d.ts
CHANGED
|
@@ -5,5 +5,5 @@ export * from "./src/metacensus/v1/topic.js";
|
|
|
5
5
|
export * from "./src/metacensus/v1/user.js";
|
|
6
6
|
export * from "./src/route-manifest.js";
|
|
7
7
|
export { protobufPackage } from "./src/metacensus/v1/common.js";
|
|
8
|
-
export { Client, ApiError, type
|
|
8
|
+
export { Client, ApiError, type ClientOptions, type Signer, type TopicRecord, type PropRecord, type VoteRecord, type UserRecord, } from "./src/client.js";
|
|
9
9
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAOA,cAAc,6BAA6B,CAAC;AAC5C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,yBAAyB,CAAC;AAGxC,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAOA,cAAc,6BAA6B,CAAC;AAC5C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,yBAAyB,CAAC;AAGxC,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAMhE,OAAO,EACL,MAAM,EACN,QAAQ,EACR,KAAK,aAAa,EAClB,KAAK,MAAM,EACX,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,UAAU,GAChB,MAAM,iBAAiB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -13,6 +13,8 @@ export * from "./src/route-manifest.js";
|
|
|
13
13
|
// `export *` can't pick one file's `protobufPackage` over another's.
|
|
14
14
|
export { protobufPackage } from "./src/metacensus/v1/common.js";
|
|
15
15
|
// Named, not `export *`: src/client.ts has one class per surface, and this
|
|
16
|
-
// entry point wants only the authenticated one.
|
|
16
|
+
// entry point wants only the authenticated one. `Client` is batteries-included;
|
|
17
|
+
// the `…Record` types are its flat reads and `Signer` its write seam. See
|
|
18
|
+
// ts/README.md, "The generated client".
|
|
17
19
|
export { Client, ApiError, } from "./src/client.js";
|
|
18
20
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,qEAAqE;AACrE,kDAAkD;AAClD,EAAE;AACF,0EAA0E;AAC1E,0CAA0C;AAE1C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,yBAAyB,CAAC;AAExC,qEAAqE;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAEhE,2EAA2E;AAC3E,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,qEAAqE;AACrE,kDAAkD;AAClD,EAAE;AACF,0EAA0E;AAC1E,0CAA0C;AAE1C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,yBAAyB,CAAC;AAExC,qEAAqE;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAEhE,2EAA2E;AAC3E,gFAAgF;AAChF,0EAA0E;AAC1E,wCAAwC;AACxC,OAAO,EACL,MAAM,EACN,QAAQ,GAOT,MAAM,iBAAiB,CAAC"}
|
package/dist/public.d.ts
CHANGED
|
@@ -2,5 +2,5 @@ export * from "./src/metacensus/public/v1/common.js";
|
|
|
2
2
|
export * from "./src/metacensus/public/v1/partner.js";
|
|
3
3
|
export * from "./src/route-manifest.js";
|
|
4
4
|
export { protobufPackage } from "./src/metacensus/public/v1/common.js";
|
|
5
|
-
export { PublicClient, ApiError, type
|
|
5
|
+
export { PublicClient, ApiError, type PublicClientOptions, } from "./src/client.js";
|
|
6
6
|
//# sourceMappingURL=public.d.ts.map
|
package/dist/public.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../public.ts"],"names":[],"mappings":"AAIA,cAAc,sCAAsC,CAAC;AACrD,cAAc,uCAAuC,CAAC;AACtD,cAAc,yBAAyB,CAAC;AAGxC,OAAO,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AAMvE,OAAO,EACL,YAAY,EACZ,QAAQ,EACR,KAAK,
|
|
1
|
+
{"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../public.ts"],"names":[],"mappings":"AAIA,cAAc,sCAAsC,CAAC;AACrD,cAAc,uCAAuC,CAAC;AACtD,cAAc,yBAAyB,CAAC;AAGxC,OAAO,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AAMvE,OAAO,EACL,YAAY,EACZ,QAAQ,EACR,KAAK,mBAAmB,GACzB,MAAM,iBAAiB,CAAC"}
|
package/dist/public.js
CHANGED
|
@@ -7,8 +7,8 @@ export * from "./src/route-manifest.js";
|
|
|
7
7
|
// `export *` can't pick one file's `protobufPackage` over another's.
|
|
8
8
|
export { protobufPackage } from "./src/metacensus/public/v1/common.js";
|
|
9
9
|
// Named, not `export *`: src/client.ts has one class per surface, and this
|
|
10
|
-
// entry point wants only PublicClient. A public-only consumer still carries
|
|
11
|
-
//
|
|
10
|
+
// entry point wants only PublicClient. A public-only consumer still carries the
|
|
11
|
+
// authenticated Client as dead code (a bundler drops it), but not the
|
|
12
12
|
// authenticated types, which is what the split is for.
|
|
13
13
|
export { PublicClient, ApiError, } from "./src/client.js";
|
|
14
14
|
//# sourceMappingURL=public.js.map
|
package/dist/public.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"public.js","sourceRoot":"","sources":["../public.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,0EAA0E;AAC1E,iEAAiE;AAEjE,cAAc,sCAAsC,CAAC;AACrD,cAAc,uCAAuC,CAAC;AACtD,cAAc,yBAAyB,CAAC;AAExC,qEAAqE;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AAEvE,2EAA2E;AAC3E,
|
|
1
|
+
{"version":3,"file":"public.js","sourceRoot":"","sources":["../public.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,0EAA0E;AAC1E,iEAAiE;AAEjE,cAAc,sCAAsC,CAAC;AACrD,cAAc,uCAAuC,CAAC;AACtD,cAAc,yBAAyB,CAAC;AAExC,qEAAqE;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AAEvE,2EAA2E;AAC3E,gFAAgF;AAChF,sEAAsE;AACtE,uDAAuD;AACvD,OAAO,EACL,YAAY,EACZ,QAAQ,GAET,MAAM,iBAAiB,CAAC"}
|
package/dist/signing.d.ts
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
export { SPEC, canonicalize,
|
|
1
|
+
export { SPEC, TYPE_GET, TYPE_COUNTERSIGN, FLAG_UP, FLAG_UV, FLAG_BE, FLAG_BS, canonicalize, interpretation, userSigningInput, countersignInput, userChallenge, countersignChallenge, authenticatorData, assert, verifyAssertion, verifyUser, verifyCountersign, participantPolicy, institutionPolicy, generateKeyPair, encodePublicKey, decodePublicKey, keyId, enrolledKey, } from "./src/signing.js";
|
|
2
|
+
export type { ClientData, Policy } from "./src/signing.js";
|
|
2
3
|
//# sourceMappingURL=signing.d.ts.map
|
package/dist/signing.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"signing.d.ts","sourceRoot":"","sources":["../signing.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,IAAI,EACJ,
|
|
1
|
+
{"version":3,"file":"signing.d.ts","sourceRoot":"","sources":["../signing.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,IAAI,EACJ,QAAQ,EACR,gBAAgB,EAChB,OAAO,EACP,OAAO,EACP,OAAO,EACP,OAAO,EACP,YAAY,EACZ,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EAChB,aAAa,EACb,oBAAoB,EACpB,iBAAiB,EACjB,MAAM,EACN,eAAe,EACf,UAAU,EACV,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,eAAe,EACf,eAAe,EACf,KAAK,EACL,WAAW,GACZ,MAAM,kBAAkB,CAAC;AAE1B,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC"}
|
package/dist/signing.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// The MetaCensus signing chain, producing the same digest as go/signing. A
|
|
2
2
|
// third entry point splitting by concern, not surface. See ts/README.md,
|
|
3
3
|
// "Signing". The runtime half is src/signing.ts.
|
|
4
|
-
export { SPEC, canonicalize,
|
|
4
|
+
export { SPEC, TYPE_GET, TYPE_COUNTERSIGN, FLAG_UP, FLAG_UV, FLAG_BE, FLAG_BS, canonicalize, interpretation, userSigningInput, countersignInput, userChallenge, countersignChallenge, authenticatorData, assert, verifyAssertion, verifyUser, verifyCountersign, participantPolicy, institutionPolicy, generateKeyPair, encodePublicKey, decodePublicKey, keyId, enrolledKey, } from "./src/signing.js";
|
|
5
5
|
//# sourceMappingURL=signing.js.map
|
package/dist/signing.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"signing.js","sourceRoot":"","sources":["../signing.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,yEAAyE;AACzE,iDAAiD;AAEjD,OAAO,EACL,IAAI,EACJ,
|
|
1
|
+
{"version":3,"file":"signing.js","sourceRoot":"","sources":["../signing.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,yEAAyE;AACzE,iDAAiD;AAEjD,OAAO,EACL,IAAI,EACJ,QAAQ,EACR,gBAAgB,EAChB,OAAO,EACP,OAAO,EACP,OAAO,EACP,OAAO,EACP,YAAY,EACZ,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EAChB,aAAa,EACb,oBAAoB,EACpB,iBAAiB,EACjB,MAAM,EACN,eAAe,EACf,UAAU,EACV,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,eAAe,EACf,eAAe,EACf,KAAK,EACL,WAAW,GACZ,MAAM,kBAAkB,CAAC"}
|
package/dist/src/client.d.ts
CHANGED
|
@@ -1,54 +1,73 @@
|
|
|
1
1
|
import type { PartnerReceipt, PartnerSubmission } from "./metacensus/public/v1/partner.js";
|
|
2
|
-
import type { LoginRequest, LogoutRequest, LogoutResponse, Session, SignUpRequest } from "./metacensus/v1/auth.js";
|
|
3
|
-
import type { HealthcheckRequest, HealthcheckResponse } from "./metacensus/v1/common.js";
|
|
4
|
-
import type { Prop, PropCreateRequest, PropGetRequest,
|
|
5
|
-
import type { Member, MemberGetRequest,
|
|
6
|
-
import type { SelfGetRequest,
|
|
7
|
-
export interface ClientRequest {
|
|
8
|
-
readonly method: string;
|
|
9
|
-
readonly path: string;
|
|
10
|
-
readonly body?: string;
|
|
11
|
-
}
|
|
12
|
-
export interface ClientResponse {
|
|
13
|
-
readonly status: number;
|
|
14
|
-
readonly body: string;
|
|
15
|
-
}
|
|
16
|
-
export type Transport = (req: ClientRequest) => Promise<ClientResponse>;
|
|
2
|
+
import type { LoginRequest, LogoutRequest, LogoutResponse, RefreshRequest, Session, SignUpRequest } from "./metacensus/v1/auth.js";
|
|
3
|
+
import type { HealthcheckRequest, HealthcheckResponse, Interpretation, Signature, User } from "./metacensus/v1/common.js";
|
|
4
|
+
import type { Prop, PropCreateRequest, PropGetRequest, PropListRequest, PropSigned, Vote, VoteListRequest, VoteSetRequest, VoteSigned } from "./metacensus/v1/prop.js";
|
|
5
|
+
import type { Member, MemberGetRequest, MemberListRequest, Topic, TopicCreateRequest, TopicGetRequest, TopicListRequest, TopicSigned } from "./metacensus/v1/topic.js";
|
|
6
|
+
import type { SelfGetRequest, UserGetRequest, UserListRequest, UserSigned } from "./metacensus/v1/user.js";
|
|
17
7
|
export declare class ApiError extends Error {
|
|
18
8
|
readonly method: string;
|
|
19
|
-
readonly
|
|
9
|
+
readonly url: string;
|
|
20
10
|
readonly status: number;
|
|
21
11
|
readonly body: string;
|
|
22
|
-
constructor(method: string,
|
|
12
|
+
constructor(method: string, url: string, status: number, body: string);
|
|
13
|
+
}
|
|
14
|
+
export interface SignResult {
|
|
15
|
+
interpretation: Interpretation;
|
|
16
|
+
signature: Signature;
|
|
17
|
+
publicKey?: string;
|
|
18
|
+
}
|
|
19
|
+
export type Signer = (content: unknown, contentType: string) => Promise<SignResult>;
|
|
20
|
+
export type PropRecord = Pick<PropSigned, "id" | "recorded"> & Prop;
|
|
21
|
+
export type TopicRecord = Pick<TopicSigned, "id" | "recorded"> & Topic;
|
|
22
|
+
export type UserRecord = Pick<UserSigned, "id" | "recorded"> & User;
|
|
23
|
+
export type VoteRecord = Pick<VoteSigned, "recorded"> & Vote;
|
|
24
|
+
export interface ClientOptions {
|
|
25
|
+
readonly baseUrl: string;
|
|
26
|
+
readonly fetch?: typeof globalThis.fetch;
|
|
27
|
+
readonly signer?: Signer;
|
|
28
|
+
readonly token?: string;
|
|
29
|
+
readonly prefix?: string;
|
|
30
|
+
readonly credentials?: RequestCredentials;
|
|
23
31
|
}
|
|
24
32
|
export declare class Client {
|
|
25
|
-
private
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
private call;
|
|
33
|
+
#private;
|
|
34
|
+
constructor(options: ClientOptions);
|
|
35
|
+
get token(): string | undefined;
|
|
29
36
|
login(req: LoginRequest): Promise<Session>;
|
|
30
|
-
signUp(req: SignUpRequest): Promise<Session>;
|
|
37
|
+
signUp(req: Omit<SignUpRequest, "userSignature" | "interpretation" | "publicKey">): Promise<Session>;
|
|
38
|
+
refresh(req: RefreshRequest): Promise<Session>;
|
|
31
39
|
logout(req: LogoutRequest): Promise<LogoutResponse>;
|
|
32
40
|
healthcheck(req: HealthcheckRequest): Promise<HealthcheckResponse>;
|
|
33
|
-
listProps(req: PropListRequest): Promise<
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
41
|
+
listProps(req: PropListRequest): Promise<PropRecord[]>;
|
|
42
|
+
listPropsSigned(req: PropListRequest): Promise<PropSigned[]>;
|
|
43
|
+
getProp(req: PropGetRequest): Promise<PropRecord>;
|
|
44
|
+
getPropSigned(req: PropGetRequest): Promise<PropSigned>;
|
|
45
|
+
createProp(req: Omit<PropCreateRequest, "userSignature" | "interpretation" | "publicKey">): Promise<PropRecord>;
|
|
46
|
+
listVotes(req: VoteListRequest): Promise<VoteRecord[]>;
|
|
47
|
+
listVotesSigned(req: VoteListRequest): Promise<VoteSigned[]>;
|
|
48
|
+
setVote(req: Omit<VoteSetRequest, "userSignature" | "interpretation" | "publicKey">): Promise<VoteRecord>;
|
|
49
|
+
listTopics(req: TopicListRequest): Promise<TopicRecord[]>;
|
|
50
|
+
listTopicsSigned(req: TopicListRequest): Promise<TopicSigned[]>;
|
|
51
|
+
getTopic(req: TopicGetRequest): Promise<TopicRecord>;
|
|
52
|
+
getTopicSigned(req: TopicGetRequest): Promise<TopicSigned>;
|
|
53
|
+
createTopic(req: Omit<TopicCreateRequest, "userSignature" | "interpretation" | "publicKey">): Promise<TopicRecord>;
|
|
54
|
+
listMembers(req: MemberListRequest): Promise<Member[]>;
|
|
42
55
|
getMember(req: MemberGetRequest): Promise<Member>;
|
|
43
|
-
listUsers(req: UserListRequest): Promise<
|
|
44
|
-
|
|
45
|
-
|
|
56
|
+
listUsers(req: UserListRequest): Promise<UserRecord[]>;
|
|
57
|
+
listUsersSigned(req: UserListRequest): Promise<UserSigned[]>;
|
|
58
|
+
getUser(req: UserGetRequest): Promise<UserRecord>;
|
|
59
|
+
getUserSigned(req: UserGetRequest): Promise<UserSigned>;
|
|
60
|
+
getSelf(req: SelfGetRequest): Promise<UserRecord>;
|
|
61
|
+
getSelfSigned(req: SelfGetRequest): Promise<UserSigned>;
|
|
62
|
+
}
|
|
63
|
+
export interface PublicClientOptions {
|
|
64
|
+
readonly baseUrl: string;
|
|
65
|
+
readonly fetch?: typeof globalThis.fetch;
|
|
66
|
+
readonly prefix?: string;
|
|
46
67
|
}
|
|
47
68
|
export declare class PublicClient {
|
|
48
|
-
private
|
|
49
|
-
|
|
50
|
-
constructor(transport: Transport, prefix?: string);
|
|
51
|
-
private call;
|
|
69
|
+
#private;
|
|
70
|
+
constructor(options: PublicClientOptions);
|
|
52
71
|
submitPartnerInterest(req: PartnerSubmission): Promise<PartnerReceipt>;
|
|
53
72
|
}
|
|
54
73
|
//# sourceMappingURL=client.d.ts.map
|
package/dist/src/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AAC3F,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"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"}
|