@reinconsole/graph 0.2.0 → 0.3.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 CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Phase 3 of **[Rein](https://github.com/bugiiiii11/rein)** — the reputation graph. Guard receipts say what agents tried to spend; gate receipts say what vendors actually earned. The graph listens to both, scores every vendor and payer it has evidence on, and feeds the scores back into enforcement on both sides of the wire.
4
4
 
5
- > **Status: v0.2 — early open-source infrastructure, live on testnet.** APIs may change before 1.0. See the live scoreboard: [Rein console](https://app.reinconsole.com).
5
+ > **Status: v0.3 — early open-source infrastructure, live on testnet.** APIs may change before 1.0. See the live scoreboard: [Rein console](https://app.reinconsole.com).
6
6
 
7
7
  ## Install
8
8
 
@@ -31,7 +31,7 @@ createGate({ screen: { check: payerCheck(graph, { denyBelow: 40 }) }, /* ... */
31
31
  - **Unknown is not bad.** The evaluator never fires `vendorReputationLt` without data, `syncVendors` withholds scores under the confidence floor, and `payerCheck` passes wallets it knows nothing about. A newcomer is served; a *confidently* bad actor is refused.
32
32
  - **No-fault refusals carry no evidence.** Rate limits, velocity caps, and rails outages at one vendor's gate never bleed into a payer's global score.
33
33
  - **One identity, one history.** `graph.link(canonical, alias)` merges subjects across id spaces — an agent's engine ULID, its paying wallets, its on-chain [ERC-8004](https://www.npmjs.com/package/@reinconsole/erc8004) identity — so evidence follows the party, not the key. Key rotation never splits a score.
34
- - **Run it as a service.** `buildGraphServer()` — remote producers `POST /v1/events`, anyone reads `GET /v1/scores/:kind/:subject` and gets the score *and* the evidence behind it. The durable variant (evidence survives restarts) lives in the [monorepo](https://github.com/bugiiiii11/rein) (`@reinconsole/store`).
34
+ - **Run it as a service.** `buildGraphServer()` — remote producers `POST /v1/events`, anyone reads `GET /v1/scores/:kind/:subject` and gets the score *and* the evidence behind it. Pass `{ auth }` (an `ApiKeyAuth` from `@reinconsole/core/auth`, or set `REIN_GRAPH_API_KEY`) and the write routes demand a key holding the `report` scope while reads stay open; without one the server binds loopback and refuses a public bind. The durable variant (evidence survives restarts) lives in the [monorepo](https://github.com/bugiiiii11/rein) (`@reinconsole/store`).
35
35
 
36
36
  Scoring weights are deliberately transparent v0.1 heuristics (`DEFAULT_WEIGHTS`, overridable) — scores are pure functions of the evidence ledger, so the model can evolve without migrations.
37
37
 
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { ReputationSubject, ReputationComponents, ReinEvent, ReputationScore, Receipt } from '@reinconsole/core';
2
2
  import { FastifyInstance } from 'fastify';
3
+ import { ApiKeyAuth } from '@reinconsole/core/auth';
3
4
 
4
5
  /** A value that may be produced synchronously or awaited (durable writes). */
5
6
  type MaybePromise<T> = T | Promise<T>;
@@ -377,11 +378,50 @@ interface PayerCheckOptions {
377
378
  */
378
379
  declare function payerCheck(graph: ReputationGraph, options?: PayerCheckOptions): (payer: string) => string | undefined;
379
380
 
381
+ interface GraphServerOptions {
382
+ /**
383
+ * API-key authentication for the WRITE routes. Omit for embedded use (the
384
+ * console world holds the graph object directly) or for a loopback-only
385
+ * process; pass an {@link ApiKeyAuth} and every write demands a `report`
386
+ * scope while reads stay open.
387
+ */
388
+ auth?: ApiKeyAuth;
389
+ }
380
390
  /**
381
391
  * Build the graph HTTP API. Remote producers POST their events here; anyone
382
392
  * can read scores with the evidence behind them. Pass a graph for tests, or
383
393
  * let it create a fresh in-memory one.
394
+ *
395
+ * READS ARE OPEN BY DESIGN and that is the whole point of a reputation graph:
396
+ * a score nobody can read governs nothing. WRITES are the asymmetry — an event
397
+ * posted here becomes evidence about a subject that did not post it — so when
398
+ * `auth` is supplied they require the `report` scope. Without `auth` the server
399
+ * is exactly as open as it always was, which is why the bins that expose it
400
+ * refuse a public bind unless a key exists or the operator says otherwise.
384
401
  */
385
- declare function buildGraphServer(graph?: ReputationGraph): FastifyInstance;
402
+ declare function buildGraphServer(graph?: ReputationGraph, options?: GraphServerOptions): FastifyInstance;
403
+ /**
404
+ * Build the graph's auth layer from the environment, or explain why there is
405
+ * none. `REIN_GRAPH_API_KEY` seeds one or more comma-separated secrets.
406
+ *
407
+ * They are seeded with `report` and nothing else: the graph has no key-issuing
408
+ * routes to bootstrap (unlike the engine, which seeds `admin` so `/v1/keys` is
409
+ * reachable), so an `admin` secret here would grant authority no route needs.
410
+ */
411
+ declare function graphAuthFromEnv(env: NodeJS.ProcessEnv): Promise<ApiKeyAuth | undefined>;
412
+ /**
413
+ * Where a graph process binds, given whether auth exists.
414
+ *
415
+ * Until D1(a) the graph had no key to trade, so the only trade available was a
416
+ * statement: `REIN_GRAPH_PUBLIC=1`. Now that writes can demand a `report` key,
417
+ * the rule matches the engine's — a key buys a public bind, and asking for one
418
+ * without a key is a startup ERROR rather than a warning. `REIN_GRAPH_PUBLIC=1`
419
+ * survives as the deliberate override for an open graph, because a read-only
420
+ * showcase is a real deployment and reads were never the exposure.
421
+ */
422
+ declare function resolveGraphHost(env: NodeJS.ProcessEnv, hasAuth?: boolean): {
423
+ host: string;
424
+ warning?: string;
425
+ };
386
426
 
387
- export { type CounterpartyLine, DEFAULT_CORRELATION_LIMIT, DEFAULT_WEIGHTS, type EventSource, EvidenceLedger, type EvidenceLedgerPort, InMemoryIntentStore, type IntentCorrelationPort, type IntentFacts, type ManualReport, type MaybePromise, type PayerCheckOptions, type ReputationExplanation, ReputationGraph, type ReputationGraphOptions, type ScoreWeights, type SubjectEvidence, type SyncOptions, type SyncedVendorScore, type VendorReputationSink, blend, blendBase, buildGraphServer, confidence, disputeComponent, longevityComponent, normalizeSubject, payerCheck, reliabilityComponent, subjectKey, volumeComponent };
427
+ export { type CounterpartyLine, DEFAULT_CORRELATION_LIMIT, DEFAULT_WEIGHTS, type EventSource, EvidenceLedger, type EvidenceLedgerPort, type GraphServerOptions, InMemoryIntentStore, type IntentCorrelationPort, type IntentFacts, type ManualReport, type MaybePromise, type PayerCheckOptions, type ReputationExplanation, ReputationGraph, type ReputationGraphOptions, type ScoreWeights, type SubjectEvidence, type SyncOptions, type SyncedVendorScore, type VendorReputationSink, blend, blendBase, buildGraphServer, confidence, disputeComponent, graphAuthFromEnv, longevityComponent, normalizeSubject, payerCheck, reliabilityComponent, resolveGraphHost, subjectKey, volumeComponent };