@elinpf/dsh-ops-access 0.2.1 → 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/lib/index.d.ts CHANGED
@@ -55,9 +55,12 @@ export interface Config {
55
55
  * Credential source: 'yaml' (default) reads the local registry file;
56
56
  * 'hub' fetches entries from a remote ops-access-hub service on every
57
57
  * call and materializes file-field content to managed local files.
58
+ * Unset + env ACCESS_HUB_URL present → 'hub' (upgrade-proof seam: the
59
+ * materialized preset file is rewritten on every suite upgrade, so the
60
+ * durable switch lives in the process environment, e.g. the systemd unit).
58
61
  */
59
62
  source?: 'yaml' | 'hub';
60
- /** Hub base URL (source: 'hub'), e.g. http://127.0.0.1:3090. */
63
+ /** Hub base URL (source: 'hub'), e.g. http://127.0.0.1:3090. Falls back to env ACCESS_HUB_URL. */
61
64
  hubUrl?: string;
62
65
  /** Hub read token (source: 'hub'); falls back to env ACCESS_HUB_READ_TOKEN. Never logged. */
63
66
  hubToken?: string;
package/lib/index.js CHANGED
@@ -57,8 +57,10 @@ export const inject = ['tools'];
57
57
  export const Config = z.object({
58
58
  registryFile: z.string().default('~/.dsh-ops/access.yaml'),
59
59
  credentialsDir: z.string().default('~/.dsh-ops/credentials'),
60
- source: z.union(['yaml', 'hub']).default('yaml'),
61
- hubUrl: z.string().default(''),
60
+ // No defaults here: an absent key must STAY absent so apply() can tell
61
+ // "unset" apart from an explicit value (the ACCESS_HUB_URL env seam).
62
+ source: z.union(['yaml', 'hub']),
63
+ hubUrl: z.string(),
62
64
  hubToken: z.string().default(''),
63
65
  hubAdminToken: z.string().default(''),
64
66
  materializeTtlMinutes: z.number().default(15),
@@ -381,7 +383,11 @@ export function apply(ctx, config) {
381
383
  // default and behaves byte-for-byte as before; hub fetches entries from a
382
384
  // remote ops-access-hub on every call and materializes file-field content
383
385
  // to managed local files under credentialsDir.
384
- const source = config.source ?? 'yaml';
386
+ // Env seam (ACCESS_HUB_URL): setting it flips an unconfigured deployment to
387
+ // hub mode. The ops preset file is re-materialized on every suite upgrade,
388
+ // so config written into it is silently dropped — the process env (systemd
389
+ // unit) is the only upgrade-proof seam.
390
+ const source = config.source ?? (process.env.ACCESS_HUB_URL ? 'hub' : 'yaml');
385
391
  // In hub mode every local credential file — materialized reads AND staged
386
392
  // writes — lives under hubCacheDir as a TTL-bound cache. credentialsDir
387
393
  // stays yaml-mode territory: the sweeper must never touch files the yaml
@@ -389,9 +395,9 @@ export function apply(ctx, config) {
389
395
  const contentDir = source === 'hub' ? expandHome(config.hubCacheDir ?? '~/.dsh-ops/hub-cache') : credentialsDir;
390
396
  let backend;
391
397
  if (source === 'hub') {
392
- const hubUrl = (config.hubUrl ?? '').replace(/\/+$/, '');
398
+ const hubUrl = (config.hubUrl || process.env.ACCESS_HUB_URL || '').replace(/\/+$/, '');
393
399
  if (hubUrl === '') {
394
- throw new Error('ops-access: source "hub" requires hubUrl (e.g. http://127.0.0.1:3090)');
400
+ throw new Error('ops-access: source "hub" requires hubUrl (e.g. http://127.0.0.1:3090) or env ACCESS_HUB_URL');
395
401
  }
396
402
  backend = new HubBackend({
397
403
  baseUrl: hubUrl,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elinpf/dsh-ops-access",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "Ops access capability seam — owns the YAML credential registry and exposes ctx.opsAccess (resolve/list/register) to provider plugins.",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",