@poppykit/server 0.1.0 → 0.2.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/API.md +4 -0
- package/CHANGELOG.md +15 -15
- package/CONTRIBUTING.md +30 -42
- package/DELIVERY.md +6 -42
- package/README.md +55 -102
- package/RELEASING.md +91 -193
- package/SECURITY.md +3 -3
- package/STORAGE.md +75 -14
- package/dist/adapter-contract.d.ts +8 -0
- package/dist/adapter-contract.js +30 -0
- package/dist/postgres-runtime.d.ts +30 -0
- package/dist/postgres-runtime.js +172 -0
- package/dist/postgres.d.ts +31 -0
- package/dist/postgres.js +303 -0
- package/migrations/postgres/0001_poppy_server.sql +16 -0
- package/package.json +18 -3
package/API.md
CHANGED
|
@@ -19,3 +19,7 @@ and do not need the optional reference issuer. Your framework owns HTTPS routing
|
|
|
19
19
|
trusted public URLs, ingress limits, request cancellation and private-error handling.
|
|
20
20
|
|
|
21
21
|
Run the [quickstart](examples/quickstart.mjs) without a listener or external service.
|
|
22
|
+
|
|
23
|
+
The optional Postgres entry point ships its adapters, `createPostgresPool`,
|
|
24
|
+
`postgresMigration`, `migratePostgres` and schema-version export; see [storage](STORAGE.md).
|
|
25
|
+
TypeScript Postgres consumers also install `@types/pg@8.23.1` as a development dependency.
|
package/CHANGELOG.md
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## 0.
|
|
3
|
+
## 0.2.0 (release candidate)
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
reference issuer, atomic targeted SQLite adapters, JSON/SSE conversation lifecycle,
|
|
7
|
-
API/browser/feedback hooks and independent-peer/crash regressions.
|
|
5
|
+
Add bundled Postgres company stores/coordinator with explicit migrations, atomic host transaction composition, savepoints and pool lifecycle.
|
|
8
6
|
|
|
9
|
-
|
|
10
|
-
- Prepare public package metadata and the initial 0.1.0 version.
|
|
11
|
-
- Preserve J8 strict TypeScript tests, real subprocess/security regressions and
|
|
12
|
-
immutable installed-package verification on Linux, macOS and Windows.
|
|
7
|
+
## 0.1.1
|
|
13
8
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
9
|
+
Documentation refresh: registry installation, runnable quickstarts, focused guides
|
|
10
|
+
and the tagged GitHub/OIDC release runbook. No runtime API, storage format or
|
|
11
|
+
third-party dependency change.
|
|
17
12
|
|
|
18
|
-
## 0.
|
|
13
|
+
## 0.1.0
|
|
19
14
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
15
|
+
Initial MIT development release, published manually. Discovery, safe HTTPS, all
|
|
16
|
+
three sign-in methods, targeted durable storage and recovery, conversations and
|
|
17
|
+
API/browser/feedback hooks. The CLI uses the client SDK with trusted secure-backend
|
|
18
|
+
adapters. J8 established strict typed tests and exact installed-artifact checks.
|
|
19
|
+
|
|
20
|
+
Version 0.x may still change APIs/storage; future changes must explain compatibility,
|
|
21
|
+
migration/reset and security implications. No stable 1.0 or external-host certification
|
|
22
|
+
is promised. Older private 0.0.0 candidates retain their own historical evidence.
|
package/CONTRIBUTING.md
CHANGED
|
@@ -1,50 +1,38 @@
|
|
|
1
1
|
# Contributing
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
[
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
and product choices. Individual extensions and demo/business workflows are excluded.
|
|
3
|
+
Follow the live draft 0.2 [specification](https://personalagentprotocol.org/docs/0.2/spec)
|
|
4
|
+
and [guides](https://personalagentprotocol.org/docs/0.2/guides). Tests/snapshots are
|
|
5
|
+
supporting evidence. Demo/business workflows and individual extensions are excluded.
|
|
6
|
+
Code is [MIT](LICENSE); confirm rights for third-party contributions.
|
|
8
7
|
|
|
9
8
|
Use Node 24.12.0, TypeScript 5.9.3 and @types/node 24.10.0.
|
|
10
|
-
Install
|
|
11
|
-
Run `npm run typecheck`, `npm run build`, `npm test` and `npm run check:docs`.
|
|
12
|
-
CI partitions tests without omitting any test file; full `npm test` remains useful
|
|
13
|
-
locally. Read [RELEASING.md](RELEASING.md) before changing workflow/release behavior.
|
|
9
|
+
Install the packageManager-pinned pnpm and run pnpm install --frozen-lockfile.
|
|
14
10
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
11
|
+
```sh
|
|
12
|
+
npm run typecheck
|
|
13
|
+
npm run build
|
|
14
|
+
npm run typecheck:tests
|
|
15
|
+
npm test
|
|
16
|
+
npm run check:docs
|
|
17
|
+
```
|
|
22
18
|
|
|
23
|
-
|
|
19
|
+
First-party tests/workers/verification helpers are canonical `.mts`. The existing
|
|
20
|
+
compiler checks the whole strict program before emitting ignored adjacent `.mjs`.
|
|
21
|
+
Failed builds remove stale outputs; no loader/type stripping substitutes for checking.
|
|
22
|
+
Run `npm run build:tests` before `node scripts/run-checks.mjs GROUP` (unit, contracts,
|
|
23
|
+
integration, validation). Groups are exhaustive/disjoint. LF source bytes are enforced
|
|
24
|
+
by Git attributes. Generated test code is outside the npm allowlist; production tests
|
|
25
|
+
import built/installed JavaScript. Release/build tools and examples may remain JS.
|
|
24
26
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
not TypeScript source. No loader or native type stripping replaces the compiler.
|
|
27
|
+
`npm run coverage` builds production and checked tests, then writes native Node
|
|
28
|
+
line/branch/function reports under `coverage/` (summary.txt, lcov.info, report.json,
|
|
29
|
+
raw/). Metrics cover loaded first-party dist JS: no production source maps or TS
|
|
30
|
+
remapping; node_modules excluded, unloaded modules listed. Raw subprocess reports
|
|
31
|
+
are retained, but arbitrary children may not merge and killed workers may not flush.
|
|
32
|
+
Installed/OS/host checks are separate evidence; no percentage proves conformance.
|
|
32
33
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
package allowlist. Retained JavaScript release/build tools and packaged examples
|
|
39
|
-
are genuine production tooling/examples; retained protocol captures are references.
|
|
40
|
-
|
|
41
|
-
Run `npm run coverage` for a production build, checked harness and native Node
|
|
42
|
-
24.12.0 line/branch/function report. `coverage/summary.txt`, `coverage/lcov.info`,
|
|
43
|
-
`coverage/report.json` and `coverage/raw/` are generated local reports. Metrics
|
|
44
|
-
refer to first-party compiled `dist` JavaScript; production emits no source maps
|
|
45
|
-
and no TypeScript remapping is claimed. Third-party `node_modules` is excluded;
|
|
46
|
-
unloaded modules are listed explicitly. Raw child-process reports are retained,
|
|
47
|
-
but arbitrary subprocess execution is not guaranteed to be merged into the native
|
|
48
|
-
runner summary, and killed/crashed workers may not flush counters. Actual installed
|
|
49
|
-
package/OS checks remain separate evidence. No percentage threshold substitutes
|
|
50
|
-
for protocol, negative/security, process and platform assertions.
|
|
34
|
+
Include callers, meaningful regression evidence and docs with behavior changes.
|
|
35
|
+
Preserve credential/destination validation, private errors and persisted data.
|
|
36
|
+
Report checks actually run and limits. Use Issues for non-sensitive defects and
|
|
37
|
+
[SECURITY.md](SECURITY.md) for vulnerabilities. Follow [RELEASING.md](RELEASING.md)
|
|
38
|
+
before tagging/publishing; obtain explicit owner authorization.
|
package/DELIVERY.md
CHANGED
|
@@ -3,48 +3,12 @@
|
|
|
3
3
|
The SDK targets Personal Agent Protocol draft 0.2. Company content, messages,
|
|
4
4
|
unknown events and partial text remain untrusted data for the host application.
|
|
5
5
|
|
|
6
|
-
## Client
|
|
6
|
+
## Client interoperability
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const conversations = createConversationClient({
|
|
13
|
-
...target, connectionId, store, clock: { now: Date.now },
|
|
14
|
-
authorizedRequest: request => auth.authorizedFetch(connectionId, request, target),
|
|
15
|
-
authorization: (id, scopes) => auth.authorization(id, scopes),
|
|
16
|
-
});
|
|
17
|
-
for await (const item of conversations.watch(conversationId, { consumer: 'ui', signal })) {
|
|
18
|
-
await processEvent(item.event);
|
|
19
|
-
await item.ack();
|
|
20
|
-
}
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
`authorization(eventOrError)` returns the single auth lifecycle's verified
|
|
24
|
-
required/granted/missing scopes and eligible methods. The UI requests consent and
|
|
25
|
-
chooses an advertised method; Device or Mediated does not require Direct support.
|
|
26
|
-
|
|
27
|
-
`read` returns one page; `drain` follows `has_more` immediately. Named consumers
|
|
28
|
-
advance only on explicit acknowledgement. `watch` accepts SSE or JSON fallback,
|
|
29
|
-
skips unknown event types, deduplicates up to 10,000 event IDs per invocation, and
|
|
30
|
-
never rewinds its cursor on a duplicate. JSON pagination has its separate
|
|
31
|
-
`maxPages` bound (default 1000), without consuming reconnect attempts. Reconnects
|
|
32
|
-
are bounded (default 4); exhaustion is explicit `reconnect_exhausted`.
|
|
33
|
-
|
|
34
|
-
`lastEventId` takes precedence over the starting cursor. On reconnect the watcher
|
|
35
|
-
sends `Last-Event-ID`. `onPartial` is display-only: a null value clears unfinished
|
|
36
|
-
text on completion/disconnect; never execute or reason from an incomplete delta.
|
|
37
|
-
Messages are actionable only after a complete `message` event. SSE frames and
|
|
38
|
-
JSON fallback are limited to 1 MiB, streams to 16 MiB, and partial text per stream
|
|
39
|
-
to 1 MiB. UTF-8 fragmentation and CR/LF/CRLF are supported.
|
|
40
|
-
|
|
41
|
-
`cursor_expired` is an explicit history gap. Inform the user, then reset a named
|
|
42
|
-
consumer and reread retained history, or supply `onHistoryGap` returning true.
|
|
43
|
-
Automatic recovery is limited to one reset per watch; it does not recover missing
|
|
44
|
-
events. Checkpoints and pending sends survive process restart with durable stores.
|
|
45
|
-
Send retries keep their original connection, issuer, endpoint, ID, body and read
|
|
46
|
-
parameters. Abort signals are invocation-local and are never persisted. Canceling
|
|
47
|
-
delivery does not cancel an accepted company action or prove a lost send failed.
|
|
8
|
+
Clients keep immutable retry targets/message IDs, explicitly acknowledge named
|
|
9
|
+
consumers and treat cursor_expired as a history gap, not recovered history. A
|
|
10
|
+
disconnected client cannot undo accepted work. The [client delivery guide](https://github.com/LMol-4/poppykit-client/blob/main/DELIVERY.md)
|
|
11
|
+
specifies watch/reconnect bounds, partial text, pagination and checkpoint handling.
|
|
48
12
|
|
|
49
13
|
## Node transport
|
|
50
14
|
|
|
@@ -67,7 +31,7 @@ the durable cursor and fresh authorization.
|
|
|
67
31
|
Metadata caching remains bounded and honors freshness, Age, validators, no-cache
|
|
68
32
|
and no-store, with a 300-second upper bound. Expired entries revalidate; 304s retain
|
|
69
33
|
prior caching directives. `resolver.invalidate(target?)` fences old pending cache
|
|
70
|
-
writes without bypassing fetch concurrency/rate limits.
|
|
34
|
+
writes without bypassing fetch concurrency/rate limits. The auth lifecycle rejects changed saved
|
|
71
35
|
issuer/endpoint/resource bindings rather than rerouting persisted work.
|
|
72
36
|
|
|
73
37
|
## Company service and retention
|
package/README.md
CHANGED
|
@@ -1,117 +1,70 @@
|
|
|
1
1
|
# PoppyKit server
|
|
2
2
|
|
|
3
|
-
TypeScript SDK for companies
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
and accept feedback. Your company owns accounts, consent UI, agent and business tools.
|
|
3
|
+
TypeScript SDK for companies implementing [Personal Agent Protocol draft 0.2](https://personalagentprotocol.org/docs/0.2/spec).
|
|
4
|
+
Verify requests, serve conversations and enforce current authority. Your company
|
|
5
|
+
supplies accounts, consent UI, agent, business tools and HTTPS routing. [MIT](LICENSE).
|
|
7
6
|
|
|
8
|
-
##
|
|
7
|
+
## Install
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
have no separate certification. Optional SQLite uses experimental `node:sqlite`
|
|
12
|
-
and requires local filesystem locking.
|
|
9
|
+
Version 0.2.0 is a release candidate until its publishing workflow completes.
|
|
13
10
|
|
|
14
|
-
|
|
15
|
-
|
|
11
|
+
Requires Node **24.12.0+** and ESM. CI tests Node 24.12.0 on Linux, macOS and Windows;
|
|
12
|
+
later majors are not separately certified. SQLite is optional/experimental and
|
|
13
|
+
requires local filesystem locking.
|
|
16
14
|
|
|
17
15
|
```sh
|
|
18
|
-
npm install
|
|
16
|
+
npm install @poppykit/server@0.2.0
|
|
19
17
|
```
|
|
20
18
|
|
|
21
|
-
|
|
22
|
-
First-publication preparation is in [RELEASING.md](RELEASING.md).
|
|
19
|
+
## Configure a service
|
|
23
20
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
The
|
|
27
|
-
|
|
28
|
-
an unauthenticated request is rejected. It starts no network listener:
|
|
29
|
-
|
|
30
|
-
```sh
|
|
31
|
-
node examples/quickstart.mjs
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
Its essential service configuration is:
|
|
21
|
+
This runnable example starts no listener and rejects an unauthenticated request.
|
|
22
|
+
`:memory:` is non-durable; use a private file and configured company sign-in hooks
|
|
23
|
+
in production. The reference issuer is optional; [existing issuers](AUTH.md) use
|
|
24
|
+
an ExternalAuthorityAdapter instead.
|
|
35
25
|
|
|
36
26
|
```js
|
|
37
27
|
import { createRequestAuthenticator, createConversationService } from '@poppykit/server';
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
28
|
+
import { createMetadataResolver, createNodeTransport, createReferenceIssuer } from '@poppykit/server/reference-auth';
|
|
29
|
+
import { SqliteCompanyDatabase } from '@poppykit/server/sqlite';
|
|
30
|
+
|
|
31
|
+
const database = new SqliteCompanyDatabase(':memory:');
|
|
32
|
+
const transport = createNodeTransport();
|
|
33
|
+
try {
|
|
34
|
+
const issuer = 'https://company.example/issuer';
|
|
35
|
+
const endpoint = 'https://company.example/conversations';
|
|
36
|
+
const auth = createReferenceIssuer({
|
|
37
|
+
issuer, tokenEndpoint: issuer + '/token', revocationEndpoint: issuer + '/revoke',
|
|
38
|
+
poppyDomains: ['company.example'], directScopes: [], resources: [endpoint],
|
|
39
|
+
metadata: createMetadataResolver(transport), store: database.issuer(issuer),
|
|
40
|
+
coordinator: database, now: Date.now,
|
|
41
|
+
});
|
|
42
|
+
const service = createConversationService({
|
|
43
|
+
endpoint, store: database.conversations(issuer), policy: auth.authority.policy,
|
|
44
|
+
authenticator: createRequestAuthenticator({ authority: auth.authority,
|
|
45
|
+
endpoints: [{ origin: 'https://company.example', pathPrefix: '/conversations', resource: endpoint }],
|
|
46
|
+
now: Date.now }), clock: { now: Date.now },
|
|
47
|
+
});
|
|
48
|
+
console.log((await service.handle(new Request(endpoint, { method: 'POST',
|
|
49
|
+
headers: { 'content-type': 'application/json' }, body: '{}' }))).status); // 401
|
|
50
|
+
} finally {
|
|
51
|
+
transport.close?.();
|
|
52
|
+
database.close();
|
|
53
|
+
}
|
|
44
54
|
```
|
|
45
55
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
Configure endpoints/trusted hooks, publish discovery/authorization metadata and
|
|
62
|
-
route token/revocation and method handlers. Your company authenticates humans,
|
|
63
|
-
protects consent with browser sessions/CSRF, delivers/verifies codes and chooses
|
|
64
|
-
scopes. Opening a consent link never approves it. See [AUTH.md](AUTH.md).
|
|
65
|
-
|
|
66
|
-
## Examples and common operations
|
|
67
|
-
|
|
68
|
-
Route protocol requests to `conversations.handle(request)`. Workers use `claim`,
|
|
69
|
-
`reply`, `finish` and lifecycle methods rather than writing rows directly. Use
|
|
70
|
-
`requireAccount(work, scopes)` or protected-operation hooks before accessing
|
|
71
|
-
account data. Model text cannot grant permission. Your application owns tool
|
|
72
|
-
execution, validation and effect idempotency; receipt/publication deduplication
|
|
73
|
-
does not make external writes exactly-once.
|
|
74
|
-
|
|
75
|
-
`createBrowserSessions` integrates your cookie store with current session authority.
|
|
76
|
-
`createFeedbackHandler` accepts validated reports, including signed-out sessions.
|
|
77
|
-
`mcpResourceMetadata` and `mcpAuthorizationError` integrate an existing MCP server
|
|
78
|
-
and issuer. See [INTEGRATIONS.md](INTEGRATIONS.md), [DELIVERY.md](DELIVERY.md) and
|
|
79
|
-
the independent generic request fixtures in `tests/independent-peer.test.mjs`.
|
|
80
|
-
|
|
81
|
-
## Errors, cancellation, retries and limits
|
|
82
|
-
|
|
83
|
-
`AuthorityError` contains a safe code, HTTP status and authentication headers.
|
|
84
|
-
Conversation handlers return protocol responses for known errors; your framework
|
|
85
|
-
must handle unexpected host failures without exposing private diagnostics. Bound
|
|
86
|
-
ingress bodies/rates before authentication. Propagate cancellation; a disconnected
|
|
87
|
-
client cannot undo accepted application work.
|
|
88
|
-
|
|
89
|
-
JSON pages and SSE events obey UTF-8 budgets. Notifications are hints; durable
|
|
90
|
-
targeted reads reconcile lost notifications. [DELIVERY.md](DELIVERY.md) documents
|
|
91
|
-
cursor/history gaps, waiting and record-specific retention. Choose
|
|
92
|
-
`stop-account-work` or `allow-accepted-work-to-finish` deliberately; new requests
|
|
93
|
-
always need current access. Immediate reference-issuer revocation visibility is
|
|
94
|
-
an implementation policy, not a universal protocol requirement.
|
|
95
|
-
|
|
96
|
-
## Storage and production responsibilities
|
|
97
|
-
|
|
98
|
-
Use one `SqliteCompanyDatabase` for reference issuer, conversations and coordinator
|
|
99
|
-
so authorization, revocation and protected writes share a transaction. SQLite
|
|
100
|
-
serializes writers and requires local filesystem locking. Supply your own
|
|
101
|
-
`ConversationStore`, `IssuerStore` and `AuthorityCoordinator` for other databases;
|
|
102
|
-
adapters enforce cross-process atomicity. [STORAGE.md](STORAGE.md) specifies
|
|
103
|
-
contracts, retention and explicit reset.
|
|
104
|
-
|
|
105
|
-
Company credentials and signing infrastructure remain your responsibility. The
|
|
106
|
-
personal-agent identity provider is a distinct trust role in the client package.
|
|
107
|
-
No model, database service, deployment vendor or demo is required.
|
|
108
|
-
|
|
109
|
-
## Reference and support
|
|
110
|
-
|
|
111
|
-
[API.md](API.md) maps public entry points and declarations to deeper guides.
|
|
112
|
-
This independent draft implementation has generic integration and packaged tests;
|
|
113
|
-
deployed issuer, proxy, database and browser policies need operator validation.
|
|
114
|
-
Individual extensions and business workflows are excluded. See
|
|
115
|
-
[CONTRIBUTING.md](CONTRIBUTING.md), [SECURITY.md](SECURITY.md),
|
|
116
|
-
[CHANGELOG.md](CHANGELOG.md) and [RELEASING.md](RELEASING.md). No public license
|
|
117
|
-
grant has been selected; licensing remains an owner decision before publication.
|
|
56
|
+
## Guides
|
|
57
|
+
|
|
58
|
+
- [Authentication](AUTH.md): external/reference issuers, consent and revocation.
|
|
59
|
+
- [Storage](STORAGE.md): shared authority coordinator, cross-process transactions and reset.
|
|
60
|
+
- [Delivery](DELIVERY.md): workers, streaming, cursors, retention and effect idempotency.
|
|
61
|
+
- [Integrations](INTEGRATIONS.md): MCP, browser cookies and feedback.
|
|
62
|
+
- [API exports](API.md), [contributing](CONTRIBUTING.md), [security](SECURITY.md),
|
|
63
|
+
[changelog](CHANGELOG.md) and [releasing](RELEASING.md).
|
|
64
|
+
|
|
65
|
+
Your ingress must bound bodies/rates before authentication, supply the trusted
|
|
66
|
+
public URL and propagate cancellation. Never trust arbitrary forwarding headers.
|
|
67
|
+
Use current policy before protected work; model text cannot grant permission.
|
|
68
|
+
Receipt/publication deduplication does not make external effects exactly-once.
|
|
69
|
+
Validate deployed database, issuer and browser policies; no model/service vendor
|
|
70
|
+
or demo application is required.
|