spfn 0.3.0-beta.13 → 0.3.0-beta.15

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
@@ -495,7 +495,7 @@ reads plain `process.env`.
495
495
  | `secret rotate [key]` | Rotate values; external secrets are flagged for manual reissue (`-a/--all`) |
496
496
  | `secret keygen` | Generate an age key pair for the SOPS no-cloud backend |
497
497
  | `secret recipients <add\|remove\|list> [age1…]` | Manage `.sops.yaml` recipients + re-encrypt |
498
- | `secret check` | Static lint — flag plaintext secret leaks; with a deployed `--env`, names in the wrong layer's file |
498
+ | `secret check` | Static lint — flag plaintext secret leaks; with a deployed `--env`, names outside their declared layer or in both files |
499
499
  | `secret export` | Decrypt and merge one deployment's layers into a 0600 dotenv file (prints names only) |
500
500
 
501
501
  Options: `-e, --env <env>` (`local` default; also `development`/`staging`/`production`),
@@ -508,11 +508,15 @@ whole of stdin as the value — one trailing newline dropped, inner newlines kep
508
508
  local and deployed targets alike. It never prompts, and refuses a terminal on stdin.
509
509
  Shaped values such as key pairs come from the app's own command, piped in.
510
510
 
511
- **Layers.** A schema entry's `layer` (`'environment'` default, or `'instance'`) says where a
512
- deployment's value comes from. Without `--instance`, `set`/`generate`/`rotate`/`list` on a
513
- deployed environment work on the `environment` names in `secrets/<env>.enc.json`; with
514
- `--instance blue`, on the `instance` names in `secrets/<env>.blue.enc.json`. A named key of
515
- the other layer is refused.
511
+ **Layers.** A schema entry's `layer` (`'environment'` or `'instance'`) pins where a
512
+ deployment's value must live; unset, the value may come from any layer. Without
513
+ `--instance`, `set`/`generate`/`rotate`/`list` on a deployed environment work on
514
+ `secrets/<env>.enc.json`; with `--instance blue`, on `secrets/<env>.blue.enc.json`. A named
515
+ key declared with the other layer is refused; a key without `layer` is accepted by either.
516
+ `--all` (and `list`) takes the names declared with the target's layer, and names without
517
+ `layer` on the environment target only — so `--all --instance blue` never fills an
518
+ instance file with names every instance shares. To give each instance its own value of
519
+ such a name, set it by name with `--instance`.
516
520
 
517
521
  **Export.**
518
522
 
@@ -525,8 +529,8 @@ Decrypts `secrets/<env>.enc.json` and — with `--instance`, when it exists —
525
529
  instance values such as port and URLs), and writes the merge to `--out`. Only names in the
526
530
  whole-app list are written; an unlisted name in an encrypted file is a warning by name.
527
531
  The export fails, writing nothing, when a required name is in no layer, a name is in two
528
- layers, an `instance` name is in the environment file, an `environment` name is in an
529
- instance layer, a value fails its validator (the error names the variable and the
532
+ layers, a name declared `instance` is in the environment file, a name declared
533
+ `environment` is in an instance layer, a value fails its validator (the error names the variable and the
530
534
  reason, never the value), or decryption fails. `--out` is required and its directory must
531
535
  exist; relative paths resolve from the working directory. The file is created 0600 beside
532
536
  the destination and renamed over it, so a failure leaves the previous file untouched
@@ -681,6 +685,39 @@ Because the package is the app's, it is resolved **from the directory the comman
681
685
  Run `spfn ops token` from the app's root; running it elsewhere reports the package as
682
686
  missing, and the message names the directory it looked in.
683
687
 
688
+ #### Can I call a surface from my own code?
689
+
690
+ Yes — the client `spfn ops` runs on is a library export, `spfn/surface`, and it reaches any
691
+ namespace a [`defineSurface`](../core/README.md#can-a-second-surface-sit-beside-_ops)
692
+ serves, not only `/_ops`:
693
+
694
+ ```typescript
695
+ import { createSurfaceClient } from 'spfn/surface';
696
+
697
+ const client = createSurfaceClient({
698
+ appUrl: 'https://app.example',
699
+ namespace: '/_app', // manifest at /_app/_manifest
700
+ token: async () => issueToken(), // string | () => Promise<string>
701
+ onWarning: message => console.error(message), // dropped commands; default: silent
702
+ });
703
+
704
+ const manifest = await client.manifest();
705
+ const usage = client.describe(manifest, 'pageAdd'); // the --describe text
706
+ const answer = await client.call('pageAdd', { params: {}, query: {}, body: { title: 'Hello' } });
707
+ // answer: { status, body } — the app's answer, relayed
708
+ ```
709
+
710
+ It keeps every check `spfn ops` makes: the manifest's shape, each command's path staying
711
+ under `<namespace>/`, module metadata, and path parameters that would decode into a dot
712
+ segment. `appUrl` must be https (`http` only against a loopback host) — refused when the
713
+ client is created, with a thrown `Error`. A manifest request that does not answer 200
714
+ throws a `SurfaceManifestError` carrying the `status`. The library prints nothing and does
715
+ not load the CLI's terminal stack; `spfn ops` is this client on `/_ops` with its own
716
+ printer.
717
+
718
+ The `spfn` package has an `exports` map: `spfn` (the CLI's index), `spfn/surface`, and
719
+ `spfn/package.json`. No other path inside the package is importable.
720
+
684
721
  ### `spfn kit`
685
722
 
686
723
  Install, verify and update a **Superfunction Kit** — a licensed product that ships as a