@cratis/pi 7.126.0 → 7.128.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/package/corpus/harnesses/copilot/instructions/profiles.instructions.md +3 -2
- package/package/corpus/harnesses/copilot/instructions/secrets.instructions.md +1 -1
- package/package/corpus/hooks/README.md +1 -1
- package/package/corpus/hooks/scripts/cratis-guard-secrets.sh +13 -2
- package/package/corpus/rules/profiles.md +3 -2
- package/package/corpus/rules/secrets.md +1 -1
- package/package/corpus/skills/cratis-arc-authentication-authorization-and-identity/SKILL.md +1 -1
- package/package/corpus/skills/cratis-arc-authentication-authorization-and-identity/references/authproxy.md +26 -0
- package/package/corpus/skills/cratis-environments-and-secrets/LICENSE +9 -0
- package/package/corpus/skills/cratis-environments-and-secrets/SKILL.md +112 -0
- package/package/corpus/skills/cratis-environments-and-secrets/references/environment-file.md +48 -0
- package/package/corpus/skills/cratis-onboarding-runtime/LICENSE +9 -0
- package/package/corpus/skills/cratis-onboarding-runtime/SKILL.md +102 -0
- package/package/corpus/skills/cratis-onboarding-runtime/references/ante-onboarding-keys.md +31 -0
- package/package/corpus/skills/cratis-onboarding-runtime/references/default-offering.md +61 -0
- package/package/corpus/skills/cratis-onboarding-runtime/references/performance.md +86 -0
- package/package/corpus/skills/cratis-onboarding-runtime/references/sign-up-review.md +52 -0
- package/package/corpus/skills/cratis-screenplay-authentication-and-onboarding/LICENSE +9 -0
- package/package/corpus/skills/cratis-screenplay-authentication-and-onboarding/SKILL.md +111 -0
- package/package/corpus/skills/cratis-screenplay-authentication-and-onboarding/references/onboarding-directives.md +89 -0
- package/package/corpus/skills/cratis-screenplay-authentication-and-onboarding/verification.json +32 -0
- package/package/corpus/skills/cratis-screenplay-command-surface/references/policy-persona-seed.md +1 -0
- package/package/corpus/skills/cratis-screenplay-model-authoring/references/language-reference.md +1 -1
- package/package/corpus/skills/cratis-screenplay-model-review/SKILL.md +2 -0
- package/package/corpus/skills/cratis-screenplay-render-and-gap-fill/references/renderability-gate.md +8 -0
- package/package/corpus/skills/cratis-screenplay-toolchain/references/neighbouring-skills.md +2 -0
- package/package/corpus/skills/cratis-screenplay-toolchain/references/screenplay-contract-exceptions.json +70 -0
- package/package/corpus/skills/cratis-showrunner-herald/LICENSE +9 -0
- package/package/corpus/skills/cratis-showrunner-herald/SKILL.md +111 -0
- package/package/corpus/skills/cratis-showrunner-herald/references/options.md +35 -0
- package/package/corpus/skills/cratis-showrunner-herald/references/templates-and-images.md +70 -0
- package/package/corpus/skills/cratis-stage-rendering-and-sandbox/SKILL.md +5 -0
- package/package/corpus/skills/cratis-stage-rendering-and-sandbox/references/rendered-application.md +48 -0
- package/package/corpus/skills/cratis-stage-rendering-and-sandbox/references/sandbox-and-specrunner.md +7 -0
- package/package/profile-catalog.json +6 -2
- package/package.json +1 -1
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Sign-up review
|
|
2
|
+
|
|
3
|
+
Requires Ante 1.6.0 or later (`Ante:Registration:Review`, `RegistrationReview` in the onboarding
|
|
4
|
+
contract). Older releases complete every sign-up without a decision and publish neither event
|
|
5
|
+
below.
|
|
6
|
+
|
|
7
|
+
Review is off by default and changes nothing while off. Turn it on when a person must be approved
|
|
8
|
+
before an organization is created.
|
|
9
|
+
|
|
10
|
+
## Flow
|
|
11
|
+
|
|
12
|
+
1. A person finishes the sign-up. With review on, Ante accepts it but holds it: no
|
|
13
|
+
`OrganizationRegistrationCompleted` is published and the registration is not complete.
|
|
14
|
+
2. Ante publishes `OrganizationRegistrationAwaitingReview` to its outbox, once per registration, on
|
|
15
|
+
the registration id. It carries the same details `OrganizationRegistrationCompleted` would carry:
|
|
16
|
+
the organization name asked for, the contact address (can be empty, never verified), the names,
|
|
17
|
+
the sign-in subject and provider, and the untrusted sign-up context.
|
|
18
|
+
3. The host shows the sign-up to its reviewers. Ante has no administrator screen and takes no
|
|
19
|
+
decision itself.
|
|
20
|
+
4. The host appends one of these to **its own store's outbox**, with the registration id as the
|
|
21
|
+
event source id:
|
|
22
|
+
- `OrganizationRegistrationApproved`: Ante completes the registration as it would have without
|
|
23
|
+
review and publishes `OrganizationRegistrationCompleted`.
|
|
24
|
+
- `OrganizationRegistrationDeclineRequested(Message)`: Ante publishes
|
|
25
|
+
`OrganizationRegistrationDeclined` with the contact address, the name the person gave and the
|
|
26
|
+
reviewer's message. `Message` is required; a blank one is refused and nothing is published.
|
|
27
|
+
|
|
28
|
+
## Rules
|
|
29
|
+
|
|
30
|
+
- A registration is decided once. A decision for a registration that was completed, was already
|
|
31
|
+
declined or was never held is ignored, so redelivery is safe and a completed registration is
|
|
32
|
+
never declined afterwards.
|
|
33
|
+
- Deduplicate `OrganizationRegistrationAwaitingReview` by registration id, like every Ante outcome:
|
|
34
|
+
delivery is at least once.
|
|
35
|
+
- If an approved registration's organization name was claimed by someone else while it waited, it
|
|
36
|
+
stays held and Ante logs a warning. Decline it with a message instead.
|
|
37
|
+
- While a sign-up is held the lobby tells the person it is waiting for review; after a decline it
|
|
38
|
+
says the sign-up was not approved, stops polling and offers no second submission.
|
|
39
|
+
- Ante emails no one. The host sends the person the declined message from
|
|
40
|
+
`OrganizationRegistrationDeclined` (Herald, `signupDeclined` template with `decline.message`).
|
|
41
|
+
- `OrganizationRegistrationDeclined` is the only outcome that says a person was turned down.
|
|
42
|
+
`InvitationRejected` says an invitation did not match what the host allows; treat it as a
|
|
43
|
+
configuration problem for whoever issued the invitation.
|
|
44
|
+
|
|
45
|
+
## Verify
|
|
46
|
+
|
|
47
|
+
1. With review on, a sign-up produces `OrganizationRegistrationAwaitingReview` and no
|
|
48
|
+
`OrganizationRegistrationCompleted`.
|
|
49
|
+
2. Appending `OrganizationRegistrationApproved` on the registration id produces
|
|
50
|
+
`OrganizationRegistrationCompleted`; appending it again produces nothing.
|
|
51
|
+
3. A decline request with a blank message publishes nothing; with a message it publishes
|
|
52
|
+
`OrganizationRegistrationDeclined` once.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
Copyright (c) Cratis. All rights reserved.
|
|
2
|
+
Licensed under the MIT license. See LICENSE file in the canonical Cratis/AI repository for the full license text.
|
|
3
|
+
|
|
4
|
+
Third-party notices
|
|
5
|
+
|
|
6
|
+
This skill adapts material from agentic-engineer by Martin Dilger and Nebulit GmbH
|
|
7
|
+
(https://github.com/Nebulit-GmbH/agentic-engineer, commit 07b0f30648d663cb588d7e2c7aa031af9dfc21f2;
|
|
8
|
+
https://nebulit.de), used with the explicit consent of Martin Dilger and Nebulit GmbH. The adapted
|
|
9
|
+
material remains credited to Martin Dilger and Nebulit GmbH.
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: cratis-screenplay-authentication-and-onboarding
|
|
3
|
+
description: Use when a `.play` model declares how users sign in or get into an application, meaning `authentication` providers, the `onboarding` block (signup, invitations, legal terms, emails) or the environment keys a provider or mail server needs. Not for personas and policies, or for running the application.
|
|
4
|
+
license: MIT
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Screenplay authentication and onboarding
|
|
8
|
+
|
|
9
|
+
Two top-level blocks say how people reach an application. `authentication` names the identity
|
|
10
|
+
providers. `onboarding` says how people get in: self-signup, who invites whom, which terms they
|
|
11
|
+
accept and which emails they receive. Both are authoring metadata, not executable behavior: the
|
|
12
|
+
reference evaluator does not run them, and whatever runs the application provisions them.
|
|
13
|
+
|
|
14
|
+
**Requires** Screenplay 4.259.0 or later for `onboarding`, the environment key listing and its
|
|
15
|
+
diagnostics (`screenplay --version`; the compiler bundled in `cratis` may be older). Older
|
|
16
|
+
releases reject the block as an unknown top-level construct.
|
|
17
|
+
|
|
18
|
+
## The line the model never crosses
|
|
19
|
+
|
|
20
|
+
The model is the same document in every environment. A client id, a client secret, an authority,
|
|
21
|
+
a sender address, a mail server and its password differ per environment, so none of them appears
|
|
22
|
+
in the model. A configuration line under a provider is a compile error (`PLAY0183`), not an
|
|
23
|
+
ignored line. The model refers to a value by a **key derived from its declarations**, and the
|
|
24
|
+
environment supplies the value. Never add the value to the model to "make it render". Creating
|
|
25
|
+
and filling the environment is [cratis-environments-and-secrets](../cratis-environments-and-secrets/SKILL.md).
|
|
26
|
+
|
|
27
|
+
## `authentication`
|
|
28
|
+
|
|
29
|
+
```text
|
|
30
|
+
authentication
|
|
31
|
+
provider EntraId
|
|
32
|
+
provider GitHub
|
|
33
|
+
provider OpenId name Partner
|
|
34
|
+
provider OpenId name Supplier
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
- At most one block for the application (`PLAY0125`); the line carries only the keyword (`PLAY0124`).
|
|
38
|
+
- Providers are `EntraId`, `GitHub`, `Google`, `Apple` and `OpenId`.
|
|
39
|
+
- A provider's **identity** is its `name` alias when it has one, otherwise the provider name.
|
|
40
|
+
Two entries with one identity are `PLAY0169`, so two `OpenId` providers each need a `name`.
|
|
41
|
+
- Typed information about the caller is the separate `identity` block, not part of `authentication`.
|
|
42
|
+
|
|
43
|
+
## `onboarding`
|
|
44
|
+
|
|
45
|
+
```text
|
|
46
|
+
onboarding
|
|
47
|
+
signup open creates tenant
|
|
48
|
+
invite tenant as Owner
|
|
49
|
+
invite member
|
|
50
|
+
by Owner, Administrator
|
|
51
|
+
grant Accountant, InvoiceManager
|
|
52
|
+
legal terms
|
|
53
|
+
file Legal/terms-of-service.md
|
|
54
|
+
file Legal/privacy-policy.md
|
|
55
|
+
offering Starter
|
|
56
|
+
emails
|
|
57
|
+
invitation file Emails/invitation.html
|
|
58
|
+
welcome file Emails/welcome.html
|
|
59
|
+
signupDeclined file Emails/signup-declined.html
|
|
60
|
+
images Emails/Images
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Read [onboarding directives](references/onboarding-directives.md) before writing or reviewing a
|
|
64
|
+
block. The diagnostics for each rule are in that reference. The rules that decide most mistakes:
|
|
65
|
+
|
|
66
|
+
- It needs `authentication` in the same application, and there is at most one block.
|
|
67
|
+
- Every line is optional and appears once. Anything that is not a directive is a compile error.
|
|
68
|
+
- **No `signup` line means self-signup is off**; every newcomer arrives by invitation.
|
|
69
|
+
`signup open creates tenant` makes a signup create a tenant, `signup open joins tenant` asks to join an existing one.
|
|
70
|
+
- Every persona in `as`, `by` and `grant` must be declared with `persona`; there are no free-text roles.
|
|
71
|
+
- `emails` names only `invitation`, `welcome` and `signupDeclined`. The sender and mail server are not in the model.
|
|
72
|
+
- `file` paths are repository-relative, like handler files. `offering` is the name of an offer the operator publishes in Box Office; a rendered application starts each new tenant on it. `signupDeclined` is sent when the host declines a held sign-up (review is not modeled; see `cratis-onboarding-runtime`).
|
|
73
|
+
|
|
74
|
+
## Environment keys
|
|
75
|
+
|
|
76
|
+
Every key is derived from a declaration, so nothing is configured twice. Keys are dotted,
|
|
77
|
+
case-sensitive paths.
|
|
78
|
+
|
|
79
|
+
| Declaration | Keys | Secret |
|
|
80
|
+
|---|---|---|
|
|
81
|
+
| each provider | `authentication.providers.<Identity>.clientId` | no |
|
|
82
|
+
| each provider | `authentication.providers.<Identity>.clientSecret` | **yes** |
|
|
83
|
+
| `EntraId` | `authentication.providers.<Identity>.tenantId` | no |
|
|
84
|
+
| `OpenId` | `authentication.providers.<Identity>.authority` | no |
|
|
85
|
+
| `onboarding` | `onboarding.email.sender`, `onboarding.email.server.host`, `.port`, `.username` | no |
|
|
86
|
+
| `onboarding` | `onboarding.email.server.password` | **yes** |
|
|
87
|
+
|
|
88
|
+
List the keys for the model instead of working them out by hand:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
screenplay environment ./model # one key per line, secrets marked "(secret)"
|
|
92
|
+
screenplay environment ./model --format json # key, secret, source, owner, description
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Pass the folder, not one file. It exits `0` when it listed keys, `1` when the model does not
|
|
96
|
+
compile (it lists nothing) and `2` when it could not run. Compare an environment with the model's
|
|
97
|
+
keys using `cratis config --missing <path>`, which exits `5` when any key is absent.
|
|
98
|
+
|
|
99
|
+
## Verify
|
|
100
|
+
|
|
101
|
+
1. `screenplay <folder> --warnaserror` exits `0` with none of the diagnostics in the directives reference.
|
|
102
|
+
2. The key listing for the folder contains exactly the keys the table above predicts for the providers and the `onboarding` block.
|
|
103
|
+
3. `grep -rn -i -E "clientSecret|password|authority" <folder>` finds no value in any `.play` file.
|
|
104
|
+
|
|
105
|
+
## Route near misses
|
|
106
|
+
|
|
107
|
+
- Personas, policies and `require`: `cratis-screenplay-command-surface`.
|
|
108
|
+
- Choosing a compiler and reading verdicts: `cratis-screenplay-toolchain`.
|
|
109
|
+
- Creating an environment, setting a secret: `cratis-environments-and-secrets`.
|
|
110
|
+
- How AuthProxy, Ante and Herald consume the contract at runtime: `cratis-onboarding-runtime`.
|
|
111
|
+
- How an Arc application trusts the proxy: `cratis-arc-authentication-authorization-and-identity`.
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Onboarding directives
|
|
2
|
+
|
|
3
|
+
A complete model: personas are declared before the blocks name them.
|
|
4
|
+
|
|
5
|
+
```text
|
|
6
|
+
policy IsOwner
|
|
7
|
+
require role "Owner"
|
|
8
|
+
|
|
9
|
+
policy IsAdministrator
|
|
10
|
+
require role "Administrator"
|
|
11
|
+
|
|
12
|
+
policy IsAccountant
|
|
13
|
+
require role "Accountant"
|
|
14
|
+
|
|
15
|
+
policy IsInvoiceManager
|
|
16
|
+
require role "InvoiceManager"
|
|
17
|
+
|
|
18
|
+
persona Owner
|
|
19
|
+
description "Owns the tenant"
|
|
20
|
+
goal "Run the tenant"
|
|
21
|
+
policy IsOwner
|
|
22
|
+
|
|
23
|
+
persona Administrator
|
|
24
|
+
description "Administers the tenant"
|
|
25
|
+
goal "Keep people onboarded"
|
|
26
|
+
policy IsAdministrator
|
|
27
|
+
|
|
28
|
+
persona Accountant
|
|
29
|
+
description "Keeps the books"
|
|
30
|
+
goal "Keep the books correct"
|
|
31
|
+
policy IsAccountant
|
|
32
|
+
|
|
33
|
+
persona InvoiceManager
|
|
34
|
+
description "Manages invoices"
|
|
35
|
+
goal "Keep invoices moving"
|
|
36
|
+
policy IsInvoiceManager
|
|
37
|
+
|
|
38
|
+
authentication
|
|
39
|
+
provider EntraId
|
|
40
|
+
provider GitHub
|
|
41
|
+
provider OpenId name Partner
|
|
42
|
+
provider OpenId name Supplier
|
|
43
|
+
|
|
44
|
+
onboarding
|
|
45
|
+
signup open creates tenant
|
|
46
|
+
invite tenant as Owner
|
|
47
|
+
invite member
|
|
48
|
+
by Owner, Administrator
|
|
49
|
+
grant Accountant, InvoiceManager
|
|
50
|
+
legal terms
|
|
51
|
+
file Legal/terms-of-service.md
|
|
52
|
+
file Legal/privacy-policy.md
|
|
53
|
+
offering Starter
|
|
54
|
+
emails
|
|
55
|
+
invitation file Emails/invitation.html
|
|
56
|
+
welcome file Emails/welcome.html
|
|
57
|
+
signupDeclined file Emails/signup-declined.html
|
|
58
|
+
images Emails/Images
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Syntax and meaning of each line of the `onboarding` block. All lines are optional and each may appear once.
|
|
62
|
+
|
|
63
|
+
| Directive | Form | Meaning |
|
|
64
|
+
|---|---|---|
|
|
65
|
+
| `signup` | `signup open creates tenant` or `signup open joins tenant` | Anyone may sign up; signing up creates a tenant or asks to join one. Absent: signup is off. |
|
|
66
|
+
| `invite tenant` | `invite tenant as <Persona>` | An invitation that creates a tenant; the invitee becomes the persona in it. One line, no body. |
|
|
67
|
+
| `invite member` | body with `by <Persona>, ...` and `grant <Persona>, ...` | An invitation into an existing tenant. `by` lists who may send it, `grant` what the invitee is given. Both are required. |
|
|
68
|
+
| `legal terms` | body of `file <path>` lines | Documents a newcomer must accept. Present means acceptance is required. |
|
|
69
|
+
| `offering` | `offering <Id>` | The Box Office offer a new tenant starts on. Absent means no licensing. |
|
|
70
|
+
| `emails` | body of `<email> file <path>` lines and `images <folder>` | Templates for `invitation`, `welcome` and `signupDeclined`, and the folder they take images from. |
|
|
71
|
+
|
|
72
|
+
## What the block deliberately lacks
|
|
73
|
+
|
|
74
|
+
No sender address, mail server, credentials or price. Those are environment values (see the key
|
|
75
|
+
table in `SKILL.md`). Languages for the emails follow the cultures of the model's `.strings` files.
|
|
76
|
+
|
|
77
|
+
## Diagnostics
|
|
78
|
+
|
|
79
|
+
| Code | Meaning | Fix |
|
|
80
|
+
|---|---|---|
|
|
81
|
+
| `PLAY0826` | The `onboarding` line carries more than the keyword. | Move content into the body. |
|
|
82
|
+
| `PLAY0827` | More than one `onboarding` block. | Merge them. |
|
|
83
|
+
| `PLAY0828` | `onboarding` without `authentication`. | Declare the providers. Draft authoring reports a warning until the folder is assembled. |
|
|
84
|
+
| `PLAY0829` | A line is not a directive, or one is malformed or incomplete. | Use the forms above. |
|
|
85
|
+
| `PLAY0830` | A directive stated twice. | Keep one. |
|
|
86
|
+
| `PLAY0831` | An invitation names a persona nothing declares. | Declare it with `persona`. |
|
|
87
|
+
| `PLAY0832` | `emails` names an email onboarding does not send. | Use `invitation`, `welcome` or `signupDeclined`. |
|
|
88
|
+
|
|
89
|
+
A missing `file` target is reported like a missing handler file: an attachment warning when files are loaded.
|
package/package/corpus/skills/cratis-screenplay-authentication-and-onboarding/verification.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"skill": "cratis-screenplay-authentication-and-onboarding",
|
|
3
|
+
"input": "Declare how people sign in and get into a Screenplay application, and say which environment keys it needs.",
|
|
4
|
+
"fixtures": [],
|
|
5
|
+
"assertions": [
|
|
6
|
+
{
|
|
7
|
+
"kind": "skill-contains",
|
|
8
|
+
"value": "PLAY0183"
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"kind": "skill-contains",
|
|
12
|
+
"value": "authentication.providers.<Identity>.clientSecret"
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"kind": "skill-contains",
|
|
16
|
+
"value": "onboarding.email.server.password"
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"kind": "skill-contains",
|
|
20
|
+
"value": "screenplay environment ./model --format json"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"kind": "skill-contains",
|
|
24
|
+
"value": "No `signup` line means self-signup is off"
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"kind": "skill-contains",
|
|
28
|
+
"value": "| `PLAY0832` |",
|
|
29
|
+
"file": "references/onboarding-directives.md"
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
}
|
package/package/corpus/skills/cratis-screenplay-command-surface/references/policy-persona-seed.md
CHANGED
|
@@ -35,6 +35,7 @@ a second (`PLAY0441`) — **or** one implementation (a tagged ` ```csharp ` bloc
|
|
|
35
35
|
runner; a code policy binds as opaque ESM v3 and needs a target to evaluate it.
|
|
36
36
|
A `persona` is authoring metadata: the binder reports it as information `PLAY0270`
|
|
37
37
|
(report-only) and it does not block binding; an unknown policy it lists is an error.
|
|
38
|
+
Personas an `onboarding` block invites or grants must be declared here; see `cratis-screenplay-authentication-and-onboarding`.
|
|
38
39
|
|
|
39
40
|
## Anonymous policy
|
|
40
41
|
|
package/package/corpus/skills/cratis-screenplay-model-authoring/references/language-reference.md
CHANGED
|
@@ -261,7 +261,7 @@ See read-surface `references/named-keys.md` for the collection-key exclusion alg
|
|
|
261
261
|
| Binds as ESM v6 (`PLAY0268` on a compiler that stops before v6) | `Automation` and `Translate` slices, reactions that produce or invoke, captures, top-level `trigger`, clock, trigger and capture specifications. The standalone `screenplay test`/MCP reference route evaluates admitted v6 actions; Stage renders supported event-triggered Automation, with remaining refusals in the Stage skill's `references/admission.md` |
|
|
262
262
|
| Reaction with trigger `reads` | Direct-producing (or code-bodied) reaction with `reads`: `PLAY0268` ("ESM v6 cannot protect that decision dependency"), non-executable. Invokes-only reaction with `reads`: information only; the invoked command must declare and protect its own decision reads. Keep the `reads`; never remove them to obtain binding |
|
|
263
263
|
| Binds as opaque code (v3); reference runner reports unsupported | Bodied reducers, bodied named rules, fenced `validate` blocks, code or file policies. A pure reducer body is the only attachment Stage admits |
|
|
264
|
-
| Information only, never blocks | `persona` (report-only: `PLAY0270`, the policies it lists must exist), `authentication`, `domain`, `seed`, descriptions and `file` provenance. A persona does not block binding and does not change behavior, so state persona scope in a description or a policy the model uses |
|
|
264
|
+
| Information only, never blocks | `persona` (report-only: `PLAY0270`, the policies it lists must exist), `authentication`, `onboarding` (see `cratis-screenplay-authentication-and-onboarding`), `domain`, `seed`, descriptions and `file` provenance. A persona does not block binding and does not change behavior, so state persona scope in a description or a policy the model uses |
|
|
265
265
|
| Binds as ESM v7 (`PLAY0268` on a compiler that stops before v7) | `generated` properties and `returns` responses, generated fixtures and `then returns`: bound and executed by the reference runner; a policy, rule or requirement that references a generated value is `PLAY0273`, and generated-concept rules select v20 with PLAY0688/0689 proof diagnostics. Stage renders supported UUID/String strategies, scalar/named responses and fixtures; unsupported types/result combinations remain `-028`/`-038` |
|
|
266
266
|
| Authorable, not executable (PLAY0268) | Systems/operations, the `numbers exact` source mode (PLAY0268; exact lowering of qualifying Double literals is the admitted v11) remain unadmitted |
|
|
267
267
|
| Concept generation strategies (ESM v15) | Required scalar generatable Uuid/String concepts; concept-owned uuid/uuidv7/ulid/typeid/nanoid/bytes strategies and admitted modifiers. Strict fixture encoding; Guarded whole-source freshness rejects Concurrency with no append/retry. Generated secrets and sequence remain refused; generated-concept rules select v20, pattern/random/rule and checksum validation select v21. Stage renders supported strategies: command-surface `references/generated-values-and-responses.md` |
|
|
@@ -97,6 +97,8 @@ model's behalf.
|
|
|
97
97
|
mode in a design model is a recorded gap, not a defect to delete. Removing protection
|
|
98
98
|
(`pii`, authorization, rules) to pass a tool is always a critical finding.
|
|
99
99
|
Protection and reaction-privilege checks: [mode compliance](references/mode-compliance.md).
|
|
100
|
+
A client id, secret, authority, sender or mail server in a model is a critical finding: those
|
|
101
|
+
belong in the environment (`cratis-screenplay-authentication-and-onboarding`).
|
|
100
102
|
12. **Root causes, classify, report** (`references/report-template.md`). Group findings that share
|
|
101
103
|
a declaration; report the root cause with its symptoms under it; severity critical, major or
|
|
102
104
|
minor; kind defect, question or note; verdict with confidence. Never apply changes.
|
package/package/corpus/skills/cratis-screenplay-render-and-gap-fill/references/renderability-gate.md
CHANGED
|
@@ -60,6 +60,14 @@ Requires Stage 4.138.0 for the Cratis renderer to render protected reads.
|
|
|
60
60
|
- Admission can pass and a Debug test still fail. Admission is never a passing test; see
|
|
61
61
|
`cratis-stage-rendering-and-sandbox` `references/render-example.md`.
|
|
62
62
|
|
|
63
|
+
## Authentication and onboarding are realized
|
|
64
|
+
A model's `authentication` and `onboarding` blocks are rendered by Stage (AuthProxy and Ante
|
|
65
|
+
configuration, personas, provisioning, emails); do not gap-fill them by hand
|
|
66
|
+
(`cratis-stage-rendering-and-sandbox` `references/rendered-application.md`). A provider kind
|
|
67
|
+
AuthProxy does not support is left out of the render with the warning `STAGE-AUTH-001`; the
|
|
68
|
+
render still publishes, so report it as a model decision, not as a hand-written provider.
|
|
69
|
+
Requires cratis CLI 3.116.0 with Stage 4.211.0 (`cratis --version`); older releases report `authentication` and `onboarding` as unrendered warnings.
|
|
70
|
+
|
|
63
71
|
## Stage issues to cite in fallback record entries
|
|
64
72
|
Historical issue pointers (not a fresh issue-state check): portable query semantics Stage#58;
|
|
65
73
|
Translate and unsupported automation forms Stage#79; mapping expressions and projection blocks Stage#117; modeled authentication
|
|
@@ -7,6 +7,8 @@ Which skill owns each task next to the toolchain.
|
|
|
7
7
|
- Construct depth: `cratis-screenplay-command-surface`, `cratis-screenplay-projections`,
|
|
8
8
|
`cratis-screenplay-read-surface`, `cratis-screenplay-captures-and-reactions`,
|
|
9
9
|
`cratis-screenplay-specifications`, `cratis-screenplay-ui-composition`.
|
|
10
|
+
- Sign-in providers, onboarding and the environment keys a model needs: `cratis-screenplay-authentication-and-onboarding`;
|
|
11
|
+
creating the environment and setting secrets: `cratis-environments-and-secrets`.
|
|
10
12
|
- Rendering and gap-fill: `cratis-screenplay-render-and-gap-fill`,
|
|
11
13
|
`cratis-stage-rendering-and-sandbox`.
|
|
12
14
|
- Running systems (Chronicle server operations through the `cratis` CLI, with its authorization boundaries): `cratis-chronicle-cli-operations`.
|
|
@@ -26,5 +26,75 @@
|
|
|
26
26
|
"kind": "diagnostic",
|
|
27
27
|
"value": "PLAY0686",
|
|
28
28
|
"reason": "Explicit retirement notice, not an active diagnostic or repair recommendation. The published contract marks PLAY0686 retired. Remove when this notice is removed or replaced."
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"file": ".cratis/ai/skills/cratis-screenplay-authentication-and-onboarding/SKILL.md",
|
|
32
|
+
"text": "screenplay environment ./model # one key per line, secrets marked \"(secret)\"",
|
|
33
|
+
"kind": "cliCommand",
|
|
34
|
+
"value": "environment",
|
|
35
|
+
"reason": "Documents the onboarding and environment-key surface of Screenplay 4.259.0, which the pinned 4.245.0 contract predates. Remove when the pinned contract moves to 4.259.0 or later (the check then reports it unnecessary)."
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"file": ".cratis/ai/skills/cratis-screenplay-authentication-and-onboarding/SKILL.md",
|
|
39
|
+
"text": "screenplay environment ./model --format json # key, secret, source, owner, description",
|
|
40
|
+
"kind": "cliCommand",
|
|
41
|
+
"value": "environment",
|
|
42
|
+
"reason": "Documents the onboarding and environment-key surface of Screenplay 4.259.0, which the pinned 4.245.0 contract predates. Remove when the pinned contract moves to 4.259.0 or later (the check then reports it unnecessary)."
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"file": ".cratis/ai/skills/cratis-screenplay-authentication-and-onboarding/SKILL.md",
|
|
46
|
+
"text": "screenplay environment ./model --format json # key, secret, source, owner, description",
|
|
47
|
+
"kind": "cliOption",
|
|
48
|
+
"value": "--format",
|
|
49
|
+
"reason": "Documents the onboarding and environment-key surface of Screenplay 4.259.0, which the pinned 4.245.0 contract predates. Remove when the pinned contract moves to 4.259.0 or later (the check then reports it unnecessary)."
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"file": ".cratis/ai/skills/cratis-screenplay-authentication-and-onboarding/references/onboarding-directives.md",
|
|
53
|
+
"text": "| `PLAY0826` | The `onboarding` line carries more than the keyword. | Move content into the body. |",
|
|
54
|
+
"kind": "diagnostic",
|
|
55
|
+
"value": "PLAY0826",
|
|
56
|
+
"reason": "Documents the onboarding and environment-key surface of Screenplay 4.259.0, which the pinned 4.245.0 contract predates. Remove when the pinned contract moves to 4.259.0 or later (the check then reports it unnecessary)."
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"file": ".cratis/ai/skills/cratis-screenplay-authentication-and-onboarding/references/onboarding-directives.md",
|
|
60
|
+
"text": "| `PLAY0827` | More than one `onboarding` block. | Merge them. |",
|
|
61
|
+
"kind": "diagnostic",
|
|
62
|
+
"value": "PLAY0827",
|
|
63
|
+
"reason": "Documents the onboarding and environment-key surface of Screenplay 4.259.0, which the pinned 4.245.0 contract predates. Remove when the pinned contract moves to 4.259.0 or later (the check then reports it unnecessary)."
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"file": ".cratis/ai/skills/cratis-screenplay-authentication-and-onboarding/references/onboarding-directives.md",
|
|
67
|
+
"text": "| `PLAY0828` | `onboarding` without `authentication`. | Declare the providers. Draft authoring reports a warning until the folder is assembled. |",
|
|
68
|
+
"kind": "diagnostic",
|
|
69
|
+
"value": "PLAY0828",
|
|
70
|
+
"reason": "Documents the onboarding and environment-key surface of Screenplay 4.259.0, which the pinned 4.245.0 contract predates. Remove when the pinned contract moves to 4.259.0 or later (the check then reports it unnecessary)."
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"file": ".cratis/ai/skills/cratis-screenplay-authentication-and-onboarding/references/onboarding-directives.md",
|
|
74
|
+
"text": "| `PLAY0829` | A line is not a directive, or one is malformed or incomplete. | Use the forms above. |",
|
|
75
|
+
"kind": "diagnostic",
|
|
76
|
+
"value": "PLAY0829",
|
|
77
|
+
"reason": "Documents the onboarding and environment-key surface of Screenplay 4.259.0, which the pinned 4.245.0 contract predates. Remove when the pinned contract moves to 4.259.0 or later (the check then reports it unnecessary)."
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"file": ".cratis/ai/skills/cratis-screenplay-authentication-and-onboarding/references/onboarding-directives.md",
|
|
81
|
+
"text": "| `PLAY0830` | A directive stated twice. | Keep one. |",
|
|
82
|
+
"kind": "diagnostic",
|
|
83
|
+
"value": "PLAY0830",
|
|
84
|
+
"reason": "Documents the onboarding and environment-key surface of Screenplay 4.259.0, which the pinned 4.245.0 contract predates. Remove when the pinned contract moves to 4.259.0 or later (the check then reports it unnecessary)."
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"file": ".cratis/ai/skills/cratis-screenplay-authentication-and-onboarding/references/onboarding-directives.md",
|
|
88
|
+
"text": "| `PLAY0831` | An invitation names a persona nothing declares. | Declare it with `persona`. |",
|
|
89
|
+
"kind": "diagnostic",
|
|
90
|
+
"value": "PLAY0831",
|
|
91
|
+
"reason": "Documents the onboarding and environment-key surface of Screenplay 4.259.0, which the pinned 4.245.0 contract predates. Remove when the pinned contract moves to 4.259.0 or later (the check then reports it unnecessary)."
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"file": ".cratis/ai/skills/cratis-screenplay-authentication-and-onboarding/references/onboarding-directives.md",
|
|
95
|
+
"text": "| `PLAY0832` | `emails` names an email onboarding does not send. | Use `invitation`, `welcome` or `signupDeclined`. |",
|
|
96
|
+
"kind": "diagnostic",
|
|
97
|
+
"value": "PLAY0832",
|
|
98
|
+
"reason": "Documents the onboarding and environment-key surface of Screenplay 4.259.0, which the pinned 4.245.0 contract predates. Remove when the pinned contract moves to 4.259.0 or later (the check then reports it unnecessary)."
|
|
29
99
|
}
|
|
30
100
|
]
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
Copyright (c) Cratis. All rights reserved.
|
|
2
|
+
Licensed under the MIT license. See LICENSE file in the canonical Cratis/AI repository for the full license text.
|
|
3
|
+
|
|
4
|
+
Third-party notices
|
|
5
|
+
|
|
6
|
+
This skill adapts material from agentic-engineer by Martin Dilger and Nebulit GmbH
|
|
7
|
+
(https://github.com/Nebulit-GmbH/agentic-engineer, commit 07b0f30648d663cb588d7e2c7aa031af9dfc21f2;
|
|
8
|
+
https://nebulit.de), used with the explicit consent of Martin Dilger and Nebulit GmbH. The adapted
|
|
9
|
+
material remains credited to Martin Dilger and Nebulit GmbH.
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: cratis-showrunner-herald
|
|
3
|
+
description: Use when a Cratis .NET application sends email such as invitations or welcome messages with Herald (`Cratis.Showrunner.Herald`), including `AddHerald`, `IEmails`, email templates and images, SMTP or the development folder transport. Not for a custom SMTP client or for Ante's token issuance.
|
|
4
|
+
license: MIT
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Herald email
|
|
8
|
+
|
|
9
|
+
Herald sends the email an application needs from template and image files, and records every
|
|
10
|
+
email as a fact. It is a **library** that runs in the application's process and keeps its state
|
|
11
|
+
as events in the application's own Chronicle event store. It is not a service.
|
|
12
|
+
|
|
13
|
+
**Requires** `Cratis.Showrunner.Herald` 1.10.0 or later and an application that is a Chronicle
|
|
14
|
+
client (`AddCratis` or `AddCratisChronicle`); check the package reference in the `.csproj`.
|
|
15
|
+
Herald records in the host application's own event store, without naming it again; set
|
|
16
|
+
`HeraldOptions.EventStore` only to use another store. Showrunner 1.13.0 or later takes the host's
|
|
17
|
+
store; an older release takes the name from the Chronicle client options, which an ASP.NET Core
|
|
18
|
+
host leaves empty, so set `EventStore` explicitly there.
|
|
19
|
+
|
|
20
|
+
## Add it
|
|
21
|
+
|
|
22
|
+
```csharp
|
|
23
|
+
builder.AddCratis();
|
|
24
|
+
builder.AddHerald(herald =>
|
|
25
|
+
{
|
|
26
|
+
herald.TemplatesFolder = Path.Combine(builder.Environment.ContentRootPath, "Emails");
|
|
27
|
+
herald.ImagesFolder = Path.Combine(builder.Environment.ContentRootPath, "Emails", "images");
|
|
28
|
+
herald.Sender = new() { Address = builder.Configuration["Herald:Sender"]!, Name = "Ledger" };
|
|
29
|
+
herald.Smtp = new()
|
|
30
|
+
{
|
|
31
|
+
Host = builder.Configuration["Herald:SmtpHost"]!,
|
|
32
|
+
Port = 587,
|
|
33
|
+
Security = SmtpSecurity.StartTls,
|
|
34
|
+
UserName = builder.Configuration["Herald:SmtpUserName"]!,
|
|
35
|
+
Password = builder.Configuration["Herald:SmtpPassword"]!
|
|
36
|
+
};
|
|
37
|
+
});
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
- **Take the sender, host, user name and password from configuration, never literals.** For a
|
|
41
|
+
Screenplay application these are the `onboarding.email.*` environment values (see
|
|
42
|
+
[cratis-environments-and-secrets](../cratis-environments-and-secrets/SKILL.md)), and the
|
|
43
|
+
password is a secret that never enters source, a log, an event or the transcript.
|
|
44
|
+
- `TemplatesFolder` is required and must exist; `Sender.Address` is required. Options are
|
|
45
|
+
validated at startup and the error names the option.
|
|
46
|
+
- Defaults worth knowing: `DefaultLanguage` `en`, `Transport` `Smtp`, `Smtp.Security` `StartTls`,
|
|
47
|
+
`Retry.MaxAttempts` 6, `PollingInterval` 5 seconds. Read [options](references/options.md) for the full table.
|
|
48
|
+
- A `signupDeclined` email is sent from `OrganizationRegistrationDeclined` with the reviewer's message as a value; see `cratis-onboarding-runtime`.
|
|
49
|
+
- Chronicle finds Herald's events through type discovery of referenced `Cratis*` packages.
|
|
50
|
+
- Run the worker in **one** application instance: delivery is at least once.
|
|
51
|
+
|
|
52
|
+
## Send
|
|
53
|
+
|
|
54
|
+
```csharp
|
|
55
|
+
await emails.Send(new EmailRequest(
|
|
56
|
+
Kind: "invitation",
|
|
57
|
+
About: context.EventSourceId,
|
|
58
|
+
To: @event.Email,
|
|
59
|
+
Values: new Dictionary<string, string> { ["invitation.link"] = @event.Link })
|
|
60
|
+
{
|
|
61
|
+
ToName = @event.Name,
|
|
62
|
+
Language = @event.Language
|
|
63
|
+
});
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Send from where the decision is made: a reactor on the fact that an invitation was issued, or an
|
|
67
|
+
Arc command. `Send` renders first and throws `EmailCannotBeRendered` without queuing anything when
|
|
68
|
+
a template, value or image is wrong; otherwise it appends `EmailQueued` against `About`, returns
|
|
69
|
+
the `EmailId` and does not wait for the server. Pass the compliance `Subject` so erasing the
|
|
70
|
+
person erases the recipient and any link that works as a credential. Report a bounce with
|
|
71
|
+
`emails.Bounced(about, emailId, kind, reason)` and leave the address out of the reason.
|
|
72
|
+
|
|
73
|
+
## Templates and images
|
|
74
|
+
|
|
75
|
+
A kind is lowercase letters, digits and dashes. The folder holds `{kind}.json` (the manifest of
|
|
76
|
+
accepted values) and `{kind}.{language}.html` per language. Read
|
|
77
|
+
[templates and images](references/templates-and-images.md) before writing either.
|
|
78
|
+
|
|
79
|
+
- Templates are strict Handlebars with only `{{value}}`, `{{#if value}}…{{else}}…{{/if}}` and `{{date value "format"}}`. Triple braces, partials and other helpers are refused.
|
|
80
|
+
- A value the manifest does not declare is an error, never an empty space. Every value is HTML-encoded.
|
|
81
|
+
- Images are PNG, JPEG or GIF referenced as `cid:name.png`. **SVG is refused**; export a PNG.
|
|
82
|
+
|
|
83
|
+
## Facts and delivery
|
|
84
|
+
|
|
85
|
+
`EmailSent`, `EmailFailed` and `EmailBounced` are in `Cratis.Showrunner.Herald.Contracts`, carry
|
|
86
|
+
the `EmailId`, and never the recipient or a value; project and react to them. They are not
|
|
87
|
+
`[Public]`: they live in the event log so the application's own projections can follow them.
|
|
88
|
+
`EmailQueued` and `EmailAttemptFailed` are Herald's own. A change to a released event is a new generation, not an edit.
|
|
89
|
+
|
|
90
|
+
For development set `Transport = EmailTransportKind.Folder` and `PickupFolder`; each email is
|
|
91
|
+
written as an `.eml` file and nothing leaves the machine. To send through a provider API, register
|
|
92
|
+
a custom `IEmailTransport` before `AddHerald`.
|
|
93
|
+
|
|
94
|
+
## Pitfalls
|
|
95
|
+
|
|
96
|
+
- Hard-coding the SMTP password in `AddHerald` or committing it: read it from configuration or the environment.
|
|
97
|
+
- Sending a new kind without its manifest, or with a value the manifest lacks: `EmailCannotBeRendered`.
|
|
98
|
+
- Putting a remote `https://` image in a template: use `cid:`.
|
|
99
|
+
- Running two worker instances: duplicate deliveries.
|
|
100
|
+
|
|
101
|
+
## Verify
|
|
102
|
+
|
|
103
|
+
1. `dotnet build` is clean and the host starts: option errors surface at startup naming the option.
|
|
104
|
+
2. With the `Folder` transport, send one email in a spec or locally and open the `.eml`: the subject, plain-text alternative and embedded image are present.
|
|
105
|
+
3. The event log has `EmailQueued` then `EmailSent` against the `About` id.
|
|
106
|
+
|
|
107
|
+
## Route near misses
|
|
108
|
+
|
|
109
|
+
- Events, reactors and projections that call Herald: `cratis-chronicle-reactor`, `cratis-chronicle-projection`.
|
|
110
|
+
- Invitation tokens, the lobby and acceptance: `cratis-onboarding-runtime`.
|
|
111
|
+
- Erasing personal data: `cratis-chronicle-compliance`.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Herald options
|
|
2
|
+
|
|
3
|
+
| Option | Default | Meaning |
|
|
4
|
+
|---|---|---|
|
|
5
|
+
| `TemplatesFolder` | required | Folder with the templates; must exist. |
|
|
6
|
+
| `ImagesFolder` | none | Folder with the images; optional when no template has an image. |
|
|
7
|
+
| `DefaultLanguage` | `en` | Language used when no template exists in the language asked for. |
|
|
8
|
+
| `Sender.Address` | required | The address the emails come from. |
|
|
9
|
+
| `Sender.Name`, `Sender.ReplyTo` | empty | Display name; where replies go. |
|
|
10
|
+
| `Look.BrandColor` | `#2563eb` | Button and link color as `#rrggbb`; templates use `{{look.brandColor}}`. |
|
|
11
|
+
| `Look.Footer` | empty | Shared footer; templates use `{{look.footer}}`. |
|
|
12
|
+
| `Transport` | `Smtp` | `Smtp`, or `Folder` to write `.eml` files. |
|
|
13
|
+
| `Smtp.Host`, `Smtp.Port` | none, `587` | The mail server. |
|
|
14
|
+
| `Smtp.Security` | `StartTls` | `StartTls` (587), `Tls` (465) or `None` (a relay on the same machine or network). |
|
|
15
|
+
| `Smtp.UserName`, `Smtp.Password` | empty | Sign-in; leave both empty for an open relay. The password is a secret. |
|
|
16
|
+
| `PickupFolder` | none | Where the `Folder` transport writes. |
|
|
17
|
+
| `Retry.MaxAttempts` | `6` | Deliveries tried before the email fails for good. |
|
|
18
|
+
| `Retry.InitialDelay`, `Retry.MaxDelay` | 30 s, 1 h | Wait after the first failure, doubling up to the maximum. |
|
|
19
|
+
| `PollingInterval` | 5 s | How often queued emails that are due are looked for. |
|
|
20
|
+
| `Namespace` | default namespace | Event store namespace for the facts. |
|
|
21
|
+
|
|
22
|
+
The server certificate is always validated; there is no switch to turn it off.
|
|
23
|
+
|
|
24
|
+
## Failure handling
|
|
25
|
+
|
|
26
|
+
| What happened | Result |
|
|
27
|
+
|---|---|
|
|
28
|
+
| Server unreachable, sign-in refused, timeout | `EmailAttemptFailed`, retried with growing delay. A bad sign-in is retried because it can be fixed while the email waits. |
|
|
29
|
+
| Server refuses message or recipient for good (550 to 554) | `EmailFailed` at once. |
|
|
30
|
+
| Last allowed attempt fails | `EmailFailed` with the attempt count. |
|
|
31
|
+
| Template or image gone when due | `EmailFailed` with zero attempts. |
|
|
32
|
+
|
|
33
|
+
Failure reasons are sentences Herald wrote, with the password and recipient address removed. An
|
|
34
|
+
unexpected failure is recorded by its kind only. Which emails are waiting comes from the event
|
|
35
|
+
log; the `QueuedEmail` read model lists emails with no outcome yet, for a count.
|