wawesome 0.14.2 → 0.15.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 +127 -59
- package/dist/index.mjs +1224 -949
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -312,31 +312,38 @@ stderr, so a redirect catches the secret and not one character besides:
|
|
|
312
312
|
npx wawesome credentials mint ci-pipeline > secret.txt
|
|
313
313
|
```
|
|
314
314
|
|
|
315
|
-
A
|
|
316
|
-
|
|
315
|
+
A capability is one cell of a grid: a verb, `read` or `write`, and the resource it acts on. A
|
|
316
|
+
credential carries the words a deploy needs, reaches every App in the workspace, and expires in
|
|
317
|
+
ninety days unless you say otherwise:
|
|
317
318
|
|
|
318
319
|
```bash
|
|
319
|
-
# reads and
|
|
320
|
-
npx wawesome credentials mint
|
|
320
|
+
# reads what ran and fires a run of what somebody else shipped, on one App, never expires
|
|
321
|
+
npx wawesome credentials mint runner -c read:apps,read:functions,read:invocations,write:runs -a prod --expires never
|
|
321
322
|
|
|
322
|
-
# ships code and attaches the domain the project declares
|
|
323
|
-
npx wawesome credentials mint ci -c
|
|
323
|
+
# ships code into an App it may create, and attaches the domain the project declares
|
|
324
|
+
npx wawesome credentials mint ci -c write:apps,write:functions,write:env,read:tenant,write:domains -a prod
|
|
324
325
|
```
|
|
325
326
|
|
|
326
327
|
| Flag | Meaning |
|
|
327
328
|
|:---------------------|:------------------------------------------------------------------------------|
|
|
328
|
-
| `-c, --capability` | `
|
|
329
|
+
| `-c, --capability` | A `{read\|write}:{resource}` word — `read:apps`, `write:functions`, `write:env`, `write:runs` and the rest. Repeatable or comma-separated. Default: `write:apps`, `write:functions`, `write:env`, `read:domains`, `read:tenant` |
|
|
330
|
+
| `--preset` | The words one job needs, by the job's name: `viewer`, `deployer`, `member`. [Which credential for which job](#which-credential-for-which-job) is what each one grants. Not with `-c` |
|
|
329
331
|
| `-a, --app` | Restrict to these Apps, by slug. Repeatable. Default: every App in the workspace |
|
|
330
332
|
| `--expires` | Days, or `never`. Default: 90 |
|
|
331
333
|
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
334
|
+
The resources are `tenant`, `apps`, `functions`, `env`, `domains`, `invocations`, `runs`,
|
|
335
|
+
`schedules`, `previews` and `egress`. A write reaches the read of the same resource, so
|
|
336
|
+
`write:functions` carries `read:functions` and there is no reason to name both. The command prints
|
|
337
|
+
the words the credential ended up with.
|
|
338
|
+
|
|
339
|
+
Some things are a person's alone, whatever a credential carries: renaming the workspace, detaching a
|
|
340
|
+
domain, widening the egress allowlist, billing, and this workspace's own credentials and members.
|
|
341
|
+
Those are not words to mint — a credential asking for one is told a person has to be at the keyboard.
|
|
335
342
|
|
|
336
343
|
An App named in a restriction does not have to exist yet. A pipeline whose first deploy creates the
|
|
337
344
|
App it was minted for is the ordinary case. A restriction bounds what a credential reads as well as
|
|
338
|
-
what it disturbs, and `
|
|
339
|
-
reach still reads the whole workspace's environment at runtime.
|
|
345
|
+
what it disturbs, and `write:functions` is the hole in it: a Function deployed into an App the
|
|
346
|
+
credential does reach still reads the whole workspace's environment at runtime.
|
|
340
347
|
|
|
341
348
|
### List them
|
|
342
349
|
|
|
@@ -470,21 +477,32 @@ concluding the platform cannot do it.
|
|
|
470
477
|
|
|
471
478
|
| Tool | What it does | Needs |
|
|
472
479
|
|:---------------------------|:------------------------------------------------------------------------|:--------------|
|
|
480
|
+
| `whoami` | The workspace, where it is administered, the words this credential carries, the Apps it reaches | nothing |
|
|
473
481
|
| `list_templates` | The template catalogue, with what each one is for | nothing |
|
|
474
482
|
| `get_template` | One template's files, environment contract and outbound providers | nothing |
|
|
475
|
-
| `list_apps` | The Apps the credential reaches, with
|
|
476
|
-
| `list_functions` | The Functions in one App, and what their live version carries | `read`
|
|
477
|
-
| `list_versions` | A Function's Versions, and which one is live | `read`
|
|
478
|
-
| `
|
|
479
|
-
| `
|
|
480
|
-
| `
|
|
481
|
-
| `
|
|
482
|
-
| `
|
|
483
|
-
| `
|
|
484
|
-
| `
|
|
485
|
-
| `
|
|
486
|
-
| `
|
|
487
|
-
| `
|
|
483
|
+
| `list_apps` | The Apps the credential reaches, each with its address and its dashboard page | `read:apps` |
|
|
484
|
+
| `list_functions` | The Functions in one App, and what their live version carries | `read:functions` |
|
|
485
|
+
| `list_versions` | A Function's Versions, and which one is live | `read:functions` |
|
|
486
|
+
| `get_function_source` | The code a Function is running, and the static files it carries | `read:functions` |
|
|
487
|
+
| `get_usage` | The Tenant's usage and headroom | `read:tenant` |
|
|
488
|
+
| `list_invocations` | Recent Invocations of a Function, failures included | `read:invocations` |
|
|
489
|
+
| `get_invocation` | One Invocation by id | `read:invocations` |
|
|
490
|
+
| `read_invocation_logs` | An Invocation's log body, a page at a time | `read:invocations` |
|
|
491
|
+
| `diagnose_latest_failure` | The latest failure, its logs and the Version that ran it, in one call | `read:invocations`, `read:functions` |
|
|
492
|
+
| `deploy_function` | Deploys code and the static files it carries | `write:functions` |
|
|
493
|
+
| `deploy_status` | How a deploy went, by the handle it answered with | `read:functions` |
|
|
494
|
+
| `rollback_function` | Puts a Version the Function already has back on its public address | `write:functions` |
|
|
495
|
+
| `set_env_var` | Sets an App's environment variable, read at the next invocation | `write:env` |
|
|
496
|
+
| `invoke_function` | Runs a deployed Function once and answers with the Invocation id | `write:runs` |
|
|
497
|
+
| `fetch_function` | Fetches one path from a Function's live Version and answers what it served | `write:runs` |
|
|
498
|
+
|
|
499
|
+
A word that writes reaches the read of the same thing, so `write:functions` needs no `read:functions`
|
|
500
|
+
beside it, and the presets below are named in exactly these words.
|
|
501
|
+
|
|
502
|
+
`whoami` is the one to call first. It answers the workspace, every word the credential carries and
|
|
503
|
+
the Apps it reaches, and it asks for nothing — so your agent can say what it is able to do before it
|
|
504
|
+
offers, rather than finding the edge by being refused in front of you. A member's session calling the
|
|
505
|
+
endpoint gets the same answer for the role they hold.
|
|
488
506
|
|
|
489
507
|
A deploy is two calls. The first says which of your files the platform does not already hold, by
|
|
490
508
|
content hash; your agent uploads those bytes to `PUT /v1/assets/{content_hash}` with the same
|
|
@@ -503,32 +521,43 @@ is all the platform permits, and an agent taking it would end yours.
|
|
|
503
521
|
### Which credential for which job
|
|
504
522
|
|
|
505
523
|
A credential carries the words its job needs and stops there. They are the same words
|
|
506
|
-
[Deploy credentials](#mint-one) mints with
|
|
524
|
+
[Deploy credentials](#mint-one) mints with, and `--preset` fills them in for you: it expands into the
|
|
525
|
+
words below before the request is built, and the command prints the words the credential ended up
|
|
526
|
+
with. A preset and `-c` together are refused rather than merged, since both name the same thing. The
|
|
527
|
+
preset is the name of the job; the words are the grant, and they are what travels.
|
|
528
|
+
|
|
529
|
+
A preset is a workspace role, and the ones offered here are the roles carrying nothing only a person
|
|
530
|
+
can hold. The name a job is minted under and the standing a member is given are one thing, rather
|
|
531
|
+
than two lists somebody has to keep level.
|
|
507
532
|
|
|
508
|
-
**Read and investigate, without the ability to ship
|
|
509
|
-
Functions, Versions, Invocations and log bodies,
|
|
510
|
-
templates. Every tool that ships code or runs it
|
|
533
|
+
**Read and investigate, without the ability to ship** — `viewer`, which is every `read:` word the
|
|
534
|
+
platform has. The agent enumerates your Apps, reads Functions, Versions, Invocations and log bodies,
|
|
535
|
+
diagnoses a failure, checks usage, and browses templates. Every tool that ships code or runs it
|
|
536
|
+
refuses:
|
|
511
537
|
|
|
512
538
|
```bash
|
|
513
|
-
npx wawesome credentials mint
|
|
539
|
+
npx wawesome credentials mint reader --preset viewer -a prod
|
|
514
540
|
```
|
|
515
541
|
|
|
516
|
-
**
|
|
517
|
-
and
|
|
542
|
+
**Ship and read back** — `deployer`, which is every read plus `write:apps`, `write:functions`,
|
|
543
|
+
`write:env` and `write:runs`. Deploy, run, diagnose, roll back, set a key. Every tool in the table:
|
|
518
544
|
|
|
519
545
|
```bash
|
|
520
|
-
npx wawesome credentials mint
|
|
546
|
+
npx wawesome credentials mint ci --preset deployer -a prod
|
|
521
547
|
```
|
|
522
548
|
|
|
523
|
-
**The whole
|
|
549
|
+
**The whole workspace** — `member`, which is the deployer's words plus `write:schedules` and
|
|
550
|
+
`write:previews`, for an agent that pauses a schedule or cuts a preview as well:
|
|
524
551
|
|
|
525
552
|
```bash
|
|
526
|
-
npx wawesome credentials mint agent
|
|
553
|
+
npx wawesome credentials mint agent --preset member -a prod
|
|
527
554
|
```
|
|
528
555
|
|
|
529
|
-
Add `domains
|
|
530
|
-
|
|
531
|
-
closed to every credential, whatever it carries.
|
|
556
|
+
Add `write:domains` where the project declares a custom domain the deploy should claim. Nothing gives
|
|
557
|
+
an agent billing, a plan change, credential management or the ability to rename your workspace: those
|
|
558
|
+
are closed to every credential, whatever it carries. Reading the workspace's name and address is not
|
|
559
|
+
among them — `whoami` answers both to any credential, which is how the agent knows where what it
|
|
560
|
+
deploys will appear.
|
|
532
561
|
|
|
533
562
|
Keep `-a` on all three. A credential restricted to one App is refused on every tool that names
|
|
534
563
|
another, which is what stops an agent working on one client's project from touching another's.
|
|
@@ -543,10 +572,18 @@ A refusal is the tool's answer, not a protocol error, and it carries the same `r
|
|
|
543
572
|
prints:
|
|
544
573
|
|
|
545
574
|
- `credential-missing-capability`. The credential does not carry a word this tool needs. The refusal
|
|
546
|
-
names
|
|
575
|
+
names the first in `missing_capability` and every one of them in `missing_capabilities`, which are
|
|
576
|
+
the words to mint a credential with. This one answers `403` rather than `200`, with a
|
|
577
|
+
`WWW-Authenticate: Bearer error="insufficient_scope"` challenge naming the same words and where
|
|
578
|
+
this endpoint's OAuth metadata is — a connector installed through consent reads it and asks its
|
|
579
|
+
human to widen the grant rather than to install again.
|
|
547
580
|
- `app-outside-credential-scope`. The credential is restricted to named Apps and this is not one of
|
|
548
581
|
them. A wider capability changes nothing here.
|
|
549
582
|
|
|
583
|
+
A `401` is the credential itself: revoked, expired, or one this platform never issued. Nothing else
|
|
584
|
+
answers one — a workspace that cannot deploy for a lapsed plan or a restriction is refused under its
|
|
585
|
+
own reason, and re-installing the connector would not fix either.
|
|
586
|
+
|
|
550
587
|
A quota refusal carries its numbers under `allowance` beside the prose, so your agent reports
|
|
551
588
|
"3 of 3 App slots" rather than handing you a sentence to read.
|
|
552
589
|
|
|
@@ -575,6 +612,33 @@ URL, serving the code its callers already hold. The CLI remembers where this dir
|
|
|
575
612
|
deployed and asks before that happens, naming both URLs. If you meant it, delete the old Function
|
|
576
613
|
from the dashboard once nothing calls it.
|
|
577
614
|
|
|
615
|
+
### A site with no handler
|
|
616
|
+
|
|
617
|
+
Leave `entry` out, write no `src/index.ts`, and point `"assets"` at the directory your build wrote
|
|
618
|
+
its pages into:
|
|
619
|
+
|
|
620
|
+
```json
|
|
621
|
+
{
|
|
622
|
+
"app": "my-app",
|
|
623
|
+
"function": "root",
|
|
624
|
+
"assets": "dist"
|
|
625
|
+
}
|
|
626
|
+
```
|
|
627
|
+
|
|
628
|
+
That deploys the pages and no code at all, and the site is live at your App's address. Nothing in the
|
|
629
|
+
file declares a kind: a project with a handler is one that has an entry point, and a project with
|
|
630
|
+
both deploys them together and rolls them back together.
|
|
631
|
+
|
|
632
|
+
An `entry` you did name and that is not there is a hard error, so a typo never quietly becomes a site
|
|
633
|
+
with nothing running behind it. Every deploy says which of the two it landed.
|
|
634
|
+
|
|
635
|
+
One thing the deploy will warn you about: everything beneath a Function's address reaches that
|
|
636
|
+
Function, so a page your root Function carries at `about/index.html` is shadowed by a sibling Function
|
|
637
|
+
named `about`. The deploy says so and names both addresses. It refuses nothing — the two Functions are
|
|
638
|
+
versioned independently, and either one may deploy first.
|
|
639
|
+
|
|
640
|
+
### Static files
|
|
641
|
+
|
|
578
642
|
Add `"assets"` to deploy static files beside your code:
|
|
579
643
|
|
|
580
644
|
```json
|
|
@@ -596,28 +660,32 @@ Files are served straight from object storage; your Function is never invoked fo
|
|
|
596
660
|
invocation is recorded. They answer on your App's own hostname and nowhere else. On the
|
|
597
661
|
development path form (`/x/<tenant>/<app>/<function>/...`) the same address reaches your handler
|
|
598
662
|
as it always has, because a file on an origin every workspace shares would be same-origin with
|
|
599
|
-
all of them.
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
663
|
+
all of them. A file beneath `assets/` carries `Cache-Control: public, max-age=31536000, immutable`,
|
|
664
|
+
so name your build output by content hash: its bytes must never change under a name a browser has
|
|
665
|
+
already cached for a year. A file outside `assets/` keeps one name across every deploy, so it carries
|
|
666
|
+
`max-age=300` instead — five minutes is inside the reach of a deploy and of a rollback, which a year
|
|
667
|
+
is not. The content type comes from the extension against a fixed allowlist and is never sniffed;
|
|
668
|
+
anything off it is served as a download.
|
|
603
669
|
|
|
604
670
|
Two rules to know about:
|
|
605
671
|
|
|
606
672
|
- **Everything beneath `assets/` is static**, whatever the deploy carries. A request there never
|
|
607
673
|
reaches your handler, and an unknown path under it is a 404 rather than a route for you to answer.
|
|
608
|
-
- **
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
674
|
+
- **A file outside `assets/` answers at its own name**, however many of them a deploy carries.
|
|
675
|
+
`favicon.ico`, `robots.txt` and a `.well-known/` directory are what that is for; hashed build
|
|
676
|
+
output belongs under `assets/`.
|
|
677
|
+
|
|
678
|
+
**A page is a file like any other.** An `index.html` your build wrote is deployed, hashed, retained
|
|
679
|
+
and billed exactly as your other files are, and it is what a directory-style address resolves to: a
|
|
680
|
+
path whose last segment carries no extension is served the `index.html` beneath it, so `/`, `/about`,
|
|
681
|
+
`/about/` and `/blog/hello` each answer with a page. A page revalidates rather than being pinned for a
|
|
682
|
+
year, wherever it sits, so deploying and refreshing is a loop that works.
|
|
683
|
+
|
|
684
|
+
**An SVG is served inert.** Nothing you deploy as a resource should be able to run script on your
|
|
685
|
+
App's own origin, and an SVG opened directly in a browser can: it runs script, and it renders whatever
|
|
686
|
+
HTML a `<foreignObject>` holds. It is served rather than refused because making it inert costs the
|
|
687
|
+
file nothing. An `<img src="logo.svg">` never ran that script and is never checked against the
|
|
688
|
+
policy, so your drawings render as they always did. Every
|
|
621
689
|
SVG and XML file carries `Content-Security-Policy: script-src 'none'; sandbox`, and only navigating
|
|
622
690
|
straight to one loses anything. Such a file is sandboxed onto an origin of its own, so its links no
|
|
623
691
|
longer navigate and a page embedding it through `<object>` or `<iframe>` cannot reach into its DOM.
|
|
@@ -732,9 +800,9 @@ npx wawesome domains
|
|
|
732
800
|
```
|
|
733
801
|
|
|
734
802
|
It prints the domain, where it got to, when the platform last checked, and the records to add. It
|
|
735
|
-
changes nothing, and a deploy credential carrying `
|
|
736
|
-
thing you do. The TXT record is minted a moment after the name is claimed, and an attach that
|
|
737
|
-
it prints a row saying so rather than dropping the record from the list. That row is what this
|
|
803
|
+
changes nothing, and a deploy credential carrying `read:domains` can run it, so a pipeline reads the
|
|
804
|
+
same thing you do. The TXT record is minted a moment after the name is claimed, and an attach that
|
|
805
|
+
outran it prints a row saying so rather than dropping the record from the list. That row is what this
|
|
738
806
|
command fills in, and it is where the deploy sends you: deploying again would change nothing, and a
|
|
739
807
|
deploy that changes nothing is refused.
|
|
740
808
|
|