@query-farm/vgi 0.39.0 → 0.40.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.
@@ -1,4 +1,4 @@
1
- import { type GrantMinter, type Protocol, type TokenResolver, VgiRpcServer } from "@query-farm/vgi-rpc";
1
+ import { GrantKeys, type GrantMinter, type Protocol, type TokenResolver, VgiRpcServer } from "@query-farm/vgi-rpc";
2
2
  /** The transport a server is being built for. Only `"http"` changes what is
3
3
  * hosted (identity); the rest are recorded so the decision lives here rather
4
4
  * than at each call site. `"iroh"` is the raw TCP upstream of a
@@ -71,6 +71,19 @@ export interface HostingOptions {
71
71
  /** Maximum age of the caller's authentication for `issue_grant`, in
72
72
  * seconds. vgi-rpc's default when omitted. */
73
73
  maxAuthAge?: number;
74
+ /**
75
+ * Sealed-grant keys (vgi-rpc `GrantKeys`), turning on the framework's own
76
+ * grants on HTTP: `issue_grant` mints `vgig1.` tokens (unless
77
+ * {@link mintGrant} is supplied) and the worker's HTTP authentication accepts
78
+ * them back as bearer credentials, as the grant's owner. When omitted,
79
+ * `VGI_RPC_GRANT_KEYS` (comma-separated base64, exactly 32 bytes each, first
80
+ * mints, all verify), `VGI_RPC_GRANT_AUDIENCE` and
81
+ * `VGI_RPC_GRANT_MAX_TTL_SECONDS` are read; `serveVgiWorker` also accepts
82
+ * `--grant-key KEY` (repeatable). Unset everywhere, nothing changes. A
83
+ * malformed key refuses to start. `null` turns grants off regardless of the
84
+ * environment.
85
+ */
86
+ grantKeys?: GrantKeys | null;
74
87
  }
75
88
  /** Server-level options passed through to `VgiRpcServer`. */
76
89
  export interface BuildRpcServerOptions {
@@ -95,3 +108,12 @@ export interface BuildRpcServerOptions {
95
108
  * on HTTP with no introspector allowlist.
96
109
  */
97
110
  export declare function buildRpcServer(primary: Protocol, hosting: HostingOptions, options: BuildRpcServerOptions): VgiRpcServer;
111
+ /**
112
+ * Collect `--grant-key KEY` / `--grant-key=KEY` (repeatable, first mints) from
113
+ * an argv, as a `GrantKeys` -- or `undefined` when none was passed, so the
114
+ * environment still applies. Audience and lifetime come from
115
+ * `VGI_RPC_GRANT_AUDIENCE` / `VGI_RPC_GRANT_MAX_TTL_SECONDS`.
116
+ *
117
+ * @throws Error A malformed key: a worker refuses to start.
118
+ */
119
+ export declare function grantKeysFromArgv(argv: readonly string[], env?: Record<string, string | undefined> | undefined): GrantKeys | undefined;
@@ -1,13 +1,21 @@
1
1
  import type { CatalogInterface } from "./catalog/interface.js";
2
2
  import type { FunctionRegistry } from "./functions/registry.js";
3
3
  import { type AuthenticateFn, type PeerResolutionOptions } from "@query-farm/vgi-rpc";
4
- import type { HostingOptions } from "./rpc-server.js";
4
+ import { type HostingOptions } from "./rpc-server.js";
5
5
  /** Environment variables `serveVgiWorker` reads. Injectable for testing. */
6
6
  export interface ServeEnv {
7
7
  PORT?: string;
8
8
  VGI_SIGNING_KEY?: string;
9
9
  VGI_TOKEN_TTL?: string;
10
10
  CORS_ORIGINS?: string;
11
+ /** Sealed-grant keys: comma-separated base64, exactly 32 bytes each, first mints. */
12
+ VGI_RPC_GRANT_KEYS?: string;
13
+ /** Audience bound into sealed grants. */
14
+ VGI_RPC_GRANT_AUDIENCE?: string;
15
+ /** Sealed-grant lifetime ceiling, seconds (default 7 days). */
16
+ VGI_RPC_GRANT_MAX_TTL_SECONDS?: string;
17
+ /** Principals allowed to call `introspect_token`, comma-separated. */
18
+ VGI_INTROSPECT_PRINCIPALS?: string;
11
19
  }
12
20
  export declare const DEFAULT_PORT = 8787;
13
21
  export declare const DEFAULT_TOKEN_TTL = 3600;
@@ -58,6 +66,10 @@ export interface ServeVgiWorkerOptions extends HostingOptions {
58
66
  quiet?: boolean;
59
67
  /** Environment source (default `process.env`). */
60
68
  env?: ServeEnv;
69
+ /** Command-line arguments to read `--grant-key KEY` (repeatable, first mints)
70
+ * from. Default `process.argv.slice(2)`. A key here takes precedence over
71
+ * `VGI_RPC_GRANT_KEYS`; an explicit {@link grantKeys} over both. */
72
+ argv?: readonly string[];
61
73
  /** Authenticates each request, returning the caller's `AuthContext`.
62
74
  * Omit for an anonymous worker (the default). */
63
75
  authenticate?: AuthenticateFn;
@@ -517,7 +517,8 @@ import {
517
517
  irohForwardedHeaderIdentityProvider,
518
518
  IROH_FORWARDED_ENDPOINT_HEADER,
519
519
  observePeerIdentity,
520
- peerIdentityPrimary
520
+ peerIdentityPrimary,
521
+ GrantKeys as GrantKeys2
521
522
  } from "@query-farm/vgi-rpc";
522
523
 
523
524
  // src/http/fetch.ts
@@ -7004,6 +7005,7 @@ function createLandingRoutes(info) {
7004
7005
 
7005
7006
  // src/rpc-server.ts
7006
7007
  import {
7008
+ GrantKeys,
7007
7009
  IdentityImpl,
7008
7010
  VgiRpcServer
7009
7011
  } from "@query-farm/vgi-rpc";
@@ -7020,7 +7022,8 @@ function buildRpcServer(primary, hosting, options) {
7020
7022
  return new VgiRpcServer(primary, {
7021
7023
  serverId: options.serverId,
7022
7024
  protocols,
7023
- identity
7025
+ identity,
7026
+ grantKeys: null
7024
7027
  });
7025
7028
  }
7026
7029
  function validatedHostedProtocols(hosting, primary) {
@@ -7063,11 +7066,13 @@ function validatedHostedProtocols(hosting, primary) {
7063
7066
  }
7064
7067
  function buildIdentity(hosting, env) {
7065
7068
  const { resolveToken, mintGrant } = hosting;
7066
- if (!resolveToken && !mintGrant)
7069
+ const grantKeys = hosting.grantKeys === undefined ? GrantKeys.fromEnv(env ?? processEnv()) : hosting.grantKeys;
7070
+ if (!resolveToken && !mintGrant && !grantKeys)
7067
7071
  return;
7068
7072
  return new IdentityImpl({
7069
7073
  resolveToken,
7070
7074
  mintGrant,
7075
+ grantKeys: grantKeys ?? undefined,
7071
7076
  introspectPrincipals: resolveToken ? resolveIntrospectPrincipals(hosting.introspectPrincipals, env) : undefined,
7072
7077
  maxAuthAge: hosting.maxAuthAge
7073
7078
  });
@@ -7088,6 +7093,26 @@ function resolveIntrospectPrincipals(explicit, env) {
7088
7093
  }
7089
7094
  return principals;
7090
7095
  }
7096
+ function processEnv() {
7097
+ return globalThis.process?.env;
7098
+ }
7099
+ function grantKeysFromArgv(argv, env = processEnv()) {
7100
+ const keys = [];
7101
+ for (let i = 0;i < argv.length; i++) {
7102
+ const a = argv[i];
7103
+ if (a === "--grant-key") {
7104
+ if (i + 1 >= argv.length)
7105
+ throw new Error("--grant-key requires a value");
7106
+ keys.push(argv[++i]);
7107
+ } else if (a.startsWith("--grant-key=")) {
7108
+ keys.push(a.slice("--grant-key=".length));
7109
+ }
7110
+ }
7111
+ if (keys.length === 0)
7112
+ return;
7113
+ const fromEnv = GrantKeys.fromEnv({ ...env ?? {}, VGI_RPC_GRANT_KEYS: keys.join(",") });
7114
+ return fromEnv ?? undefined;
7115
+ }
7091
7116
 
7092
7117
  // src/http/fetch.ts
7093
7118
  var requestAuthStorage;
@@ -7235,7 +7260,8 @@ function createVgiWorkerFetch(opts) {
7235
7260
  resolveToken: opts.resolveToken,
7236
7261
  mintGrant: opts.mintGrant,
7237
7262
  introspectPrincipals: opts.introspectPrincipals,
7238
- maxAuthAge: opts.maxAuthAge
7263
+ maxAuthAge: opts.maxAuthAge,
7264
+ grantKeys: opts.grantKeys !== undefined ? opts.grantKeys : grantKeysFromArgv(opts.argv ?? process.argv.slice(2), env) ?? GrantKeys2.fromEnv(env)
7239
7265
  });
7240
7266
  }
7241
7267
  function serveVgiWorker(opts) {
@@ -7283,4 +7309,4 @@ export {
7283
7309
  serveVgiWorker
7284
7310
  };
7285
7311
 
7286
- //# debugId=1342AF43ED836A9764756E2164756E21
7312
+ //# debugId=9A6DC12C2CA522B864756E2164756E21