@tatara/cli 0.11.1 → 0.13.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/dist/bin.mjs +3162 -2936
- package/package.json +1 -1
- package/templates/features/authz/files/src/core/authz/system-roles.ts +6 -3
- package/templates/features/authz/files+auth-orgs/tests/tatara/authz-org-creator.test.ts +26 -0
- package/templates/features/base/files/AGENTS.md +3 -0
- package/templates/features/notifications/files/src/modules/notifications/services/notifier.ts +3 -0
- package/templates/features/observability/files/src/apps/instrument.ts +2 -3
- package/templates/versions.json +7 -6
package/package.json
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/**
|
|
2
|
+
* Built-in roles. Add a key here, then grant it permissions in module permission files. A role is
|
|
3
|
+
* held only by those it's assigned to, unless `heldBy` says every org member or an identity role.
|
|
4
|
+
*/
|
|
2
5
|
export const SYSTEM_ROLES = [
|
|
3
|
-
|
|
4
|
-
{ key: "member", name: "Member", description: "
|
|
6
|
+
// tatara:slot admin
|
|
7
|
+
{ key: "member", name: "Member", description: "Every member of the org.", heldBy: "members" },
|
|
5
8
|
// tatara:slot roles
|
|
6
9
|
] as const;
|
|
7
10
|
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, it } from "vitest";
|
|
2
|
+
import { authz } from "#core/authz/index";
|
|
3
|
+
import { api } from "#tests/helpers/api";
|
|
4
|
+
import { authenticate } from "#tests/helpers/auth";
|
|
5
|
+
import { resetDatabase } from "#tests/helpers/db";
|
|
6
|
+
|
|
7
|
+
beforeEach(async () => {
|
|
8
|
+
await resetDatabase();
|
|
9
|
+
await authz.syncSystemRoles();
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
describe("an organization's creator", () => {
|
|
13
|
+
it("is its admin", async () => {
|
|
14
|
+
const user = await authenticate();
|
|
15
|
+
const created = await api.post<{ id: string }>(
|
|
16
|
+
"/api/auth/organization/create",
|
|
17
|
+
{ name: "New School", slug: `new-${crypto.randomUUID()}` },
|
|
18
|
+
{ headers: user.headers },
|
|
19
|
+
);
|
|
20
|
+
expect(created.status).toBe(200);
|
|
21
|
+
const me = await api.get<{ data: { roles: string[] } }>("/api/authorization/me", {
|
|
22
|
+
headers: { ...user.headers, "x-org-id": created.body.id },
|
|
23
|
+
});
|
|
24
|
+
expect(me.body.data.roles).toContain("admin");
|
|
25
|
+
});
|
|
26
|
+
});
|
|
@@ -41,6 +41,7 @@ __PM_EXEC__ tatara make route|service|command <name> --module <module>
|
|
|
41
41
|
__PM_EXEC__ tatara run --list # app commands
|
|
42
42
|
__PM_EXEC__ tatara routes # every route and what protects it
|
|
43
43
|
__PM_EXEC__ tatara upgrade # after bumping @tatara/cli: run its codemods, sync, verify
|
|
44
|
+
__PM_EXEC__ tatara add <add-on…> # add jobs, cache, realtime… to this app later
|
|
44
45
|
```
|
|
45
46
|
|
|
46
47
|
## HTTP
|
|
@@ -73,6 +74,8 @@ __PM_EXEC__ tatara upgrade # after bumping @tatara/cli: run its co
|
|
|
73
74
|
Never `Math.random()` for anything a user could guess.
|
|
74
75
|
- User text: `text({ max })` and `url()` from `@tatara/core` in validators clean and check it (control,
|
|
75
76
|
invisible and bidi characters, whitespace; only http(s) links). Escape when you render HTML.
|
|
77
|
+
Rich text users write: `sanitizeHtml(html)` (or `"email"` for templates) from `@tatara/core/html`
|
|
78
|
+
once `sanitize-html` is a dependency.
|
|
76
79
|
|
|
77
80
|
## Deploying
|
|
78
81
|
|
package/templates/features/notifications/files/src/modules/notifications/services/notifier.ts
CHANGED
|
@@ -52,6 +52,9 @@ export const { notify, consumers } = createNotifier<NotificationsOf<typeof notif
|
|
|
52
52
|
? { email: user.email ?? null, phone: user.phoneNumber ?? null, language: user.language ?? null }
|
|
53
53
|
: null;
|
|
54
54
|
},
|
|
55
|
+
// who gets what is yours to decide: preferences, quiet hours… ({ userId, notification, channel,
|
|
56
|
+
// data }); false skips that channel for that user
|
|
57
|
+
allow: () => true,
|
|
55
58
|
sms: sms(),
|
|
56
59
|
push: push(),
|
|
57
60
|
// tatara:slot senders
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
// Loaded before the app (`node --import ./dist/apps/instrument.mjs …`, set in the Dockerfile):
|
|
2
2
|
// instrumentation can only patch libraries imported after it, so app code comes in dynamically.
|
|
3
|
-
import { register } from "node:module";
|
|
4
|
-
|
|
5
3
|
const { env } = await import("#core/config/env");
|
|
6
4
|
|
|
7
5
|
if (env.OTEL_EXPORTER_OTLP_ENDPOINT) {
|
|
8
|
-
|
|
6
|
+
const { registerInstrumentationHooks } = await import("@tatara/observability/hooks");
|
|
7
|
+
await registerInstrumentationHooks();
|
|
9
8
|
const { startTelemetry } = await import("@tatara/observability");
|
|
10
9
|
startTelemetry({
|
|
11
10
|
serviceName: env.OTEL_SERVICE_NAME,
|
package/templates/versions.json
CHANGED
|
@@ -31,13 +31,13 @@
|
|
|
31
31
|
"@aws-sdk/s3-request-presigner": "3.1152.0",
|
|
32
32
|
"nodemailer": "10.1.1",
|
|
33
33
|
"@types/nodemailer": "8.0.2",
|
|
34
|
-
"@tatara/core": "0.1.
|
|
34
|
+
"@tatara/core": "0.1.3",
|
|
35
35
|
"@tatara/http": "0.1.2",
|
|
36
36
|
"@tatara/db": "0.2.2",
|
|
37
37
|
"@tatara/testing": "0.1.1",
|
|
38
|
-
"@tatara/auth": "0.2.
|
|
38
|
+
"@tatara/auth": "0.2.1",
|
|
39
39
|
"@tatara/keycloak": "0.1.2",
|
|
40
|
-
"@tatara/authz": "0.
|
|
40
|
+
"@tatara/authz": "0.5.0",
|
|
41
41
|
"@tatara/storage": "0.2.0",
|
|
42
42
|
"@tatara/email": "0.3.0",
|
|
43
43
|
"@tatara/i18n": "0.1.0",
|
|
@@ -45,13 +45,13 @@
|
|
|
45
45
|
"@tatara/cache": "0.1.0",
|
|
46
46
|
"openapi-typescript": "7.13.0",
|
|
47
47
|
"kafkajs": "2.2.4",
|
|
48
|
-
"@tatara/notifications": "0.
|
|
48
|
+
"@tatara/notifications": "0.2.0",
|
|
49
49
|
"@tatara/realtime": "0.1.0",
|
|
50
50
|
"socket.io": "4.8.4",
|
|
51
51
|
"socket.io-client": "4.8.4",
|
|
52
52
|
"@socket.io/redis-adapter": "8.3.0",
|
|
53
53
|
"@socket.io/redis-emitter": "5.1.0",
|
|
54
|
-
"@tatara/observability": "0.
|
|
54
|
+
"@tatara/observability": "0.2.0",
|
|
55
55
|
"@opentelemetry/api": "1.10.0",
|
|
56
56
|
"@opentelemetry/sdk-node": "0.300.0",
|
|
57
57
|
"@opentelemetry/sdk-trace": "3.0.0",
|
|
@@ -61,5 +61,6 @@
|
|
|
61
61
|
"@opentelemetry/exporter-metrics-otlp-http": "0.300.0",
|
|
62
62
|
"@opentelemetry/auto-instrumentations-node": "0.82.0",
|
|
63
63
|
"@opentelemetry/instrumentation": "0.300.0",
|
|
64
|
-
"@hono/otel": "1.3.0"
|
|
64
|
+
"@hono/otel": "1.3.0",
|
|
65
|
+
"import-in-the-middle": "3.5.3"
|
|
65
66
|
}
|