@c9up/station 0.1.15 → 0.1.16
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/StationProvider.d.ts +51 -11
- package/dist/StationProvider.d.ts.map +1 -1
- package/dist/StationProvider.js +484 -163
- package/dist/StationProvider.js.map +1 -1
- package/dist/columns.d.ts +38 -0
- package/dist/columns.d.ts.map +1 -0
- package/dist/columns.js +93 -0
- package/dist/columns.js.map +1 -0
- package/dist/defineResource.d.ts.map +1 -1
- package/dist/defineResource.js +24 -0
- package/dist/defineResource.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/loginLimiter.d.ts +41 -0
- package/dist/loginLimiter.d.ts.map +1 -0
- package/dist/loginLimiter.js +80 -0
- package/dist/loginLimiter.js.map +1 -0
- package/dist/types.d.ts +74 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/views/form.d.ts +6 -0
- package/dist/views/form.d.ts.map +1 -1
- package/dist/views/form.js +4 -4
- package/dist/views/form.js.map +1 -1
- package/dist/views/login.d.ts +2 -2
- package/dist/views/login.js +2 -2
- package/package.json +1 -1
- package/src/StationProvider.ts +675 -184
- package/src/columns.ts +136 -0
- package/src/defineResource.ts +32 -0
- package/src/index.ts +7 -0
- package/src/loginLimiter.ts +110 -0
- package/src/types.ts +86 -1
- package/src/views/form.ts +26 -4
- package/src/views/login.ts +2 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loginLimiter.js","sourceRoot":"","sources":["../src/loginLimiter.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -13,9 +13,44 @@ export interface AuditEvent {
|
|
|
13
13
|
readonly userId?: unknown;
|
|
14
14
|
readonly before?: Readonly<Record<string, unknown>>;
|
|
15
15
|
readonly after?: Readonly<Record<string, unknown>>;
|
|
16
|
+
/**
|
|
17
|
+
* On an edit, the secret columns whose value changed. Their values are
|
|
18
|
+
* replaced with `"[redacted]"` in `before`/`after` (unless the resource
|
|
19
|
+
* sets `auditSecrets`), so this is how a password change stays visible.
|
|
20
|
+
*/
|
|
21
|
+
readonly redactedChanges?: ReadonlyArray<string>;
|
|
22
|
+
/** Client IP of the request that made the change. */
|
|
23
|
+
readonly ip?: string;
|
|
24
|
+
readonly userAgent?: string;
|
|
25
|
+
/** `X-Request-Id` of that request, when the proxy or client set one. */
|
|
26
|
+
readonly requestId?: string;
|
|
16
27
|
readonly at: Date;
|
|
17
28
|
}
|
|
18
29
|
export type AuditSink = (event: AuditEvent) => void | Promise<void>;
|
|
30
|
+
/** What a {@link SecurityAuditEvent} records. */
|
|
31
|
+
export type SecurityAuditAction = "login" | "login_failed" | "login_throttled" | "logout" | "denied" | "csrf_denied";
|
|
32
|
+
/**
|
|
33
|
+
* A sign-in, sign-out or refusal on the admin surface, sent to the
|
|
34
|
+
* `station.audit` sink so brute force and probing show up in the trail.
|
|
35
|
+
*/
|
|
36
|
+
export interface SecurityAuditEvent {
|
|
37
|
+
readonly action: SecurityAuditAction;
|
|
38
|
+
/** The authenticated user, when one is known. */
|
|
39
|
+
readonly userId?: unknown;
|
|
40
|
+
/** The email a sign-in attempt submitted. */
|
|
41
|
+
readonly identifier?: string;
|
|
42
|
+
/** For `denied` on a resource action: its slug, action and permission. */
|
|
43
|
+
readonly resource?: string;
|
|
44
|
+
readonly resourceAction?: ResourceAction;
|
|
45
|
+
/** For `denied`: the permission or role that was missing. */
|
|
46
|
+
readonly permission?: string;
|
|
47
|
+
readonly path?: string;
|
|
48
|
+
readonly ip?: string;
|
|
49
|
+
readonly userAgent?: string;
|
|
50
|
+
readonly requestId?: string;
|
|
51
|
+
readonly at: Date;
|
|
52
|
+
}
|
|
53
|
+
export type SecurityAuditSink = (event: SecurityAuditEvent) => void | Promise<void>;
|
|
19
54
|
/**
|
|
20
55
|
* Per-field override for the auto-generated form (Story 54.5). Station
|
|
21
56
|
* infers the form from the entity's `@Column` metadata; consumers can
|
|
@@ -23,7 +58,10 @@ export type AuditSink = (event: AuditEvent) => void | Promise<void>;
|
|
|
23
58
|
* others.
|
|
24
59
|
*/
|
|
25
60
|
export interface FormFieldOverride {
|
|
26
|
-
/**
|
|
61
|
+
/**
|
|
62
|
+
* Hide the field from the form. A hidden field is not writable either: a
|
|
63
|
+
* body carrying it is ignored and a hidden boolean keeps its stored value.
|
|
64
|
+
*/
|
|
27
65
|
hidden?: boolean;
|
|
28
66
|
/** Override the rendered `<input type>`. */
|
|
29
67
|
inputType?: "text" | "number" | "email" | "password" | "date" | "datetime-local" | "checkbox" | "textarea";
|
|
@@ -34,6 +72,14 @@ export interface FormFieldOverride {
|
|
|
34
72
|
/** Mark the field as required at the HTML level. */
|
|
35
73
|
required?: boolean;
|
|
36
74
|
}
|
|
75
|
+
/** Per-view options for the list and show pages. */
|
|
76
|
+
export interface ResourceViewOptions {
|
|
77
|
+
/**
|
|
78
|
+
* The columns the view renders, in this order. When omitted, every column
|
|
79
|
+
* except secrets (`serializeAs: null` or a credential-like name) is shown.
|
|
80
|
+
*/
|
|
81
|
+
columns?: ReadonlyArray<string>;
|
|
82
|
+
}
|
|
37
83
|
export interface ResourceOptions<TEntity> {
|
|
38
84
|
/** Entity class (Atlas `@Entity()`-decorated constructor). */
|
|
39
85
|
entity: new (...args: never[]) => TEntity;
|
|
@@ -49,6 +95,13 @@ export interface ResourceOptions<TEntity> {
|
|
|
49
95
|
* so apps don't silently lose audit visibility.
|
|
50
96
|
*/
|
|
51
97
|
audit?: AuditSink;
|
|
98
|
+
/**
|
|
99
|
+
* Hand secret column values (`serializeAs: null` or a credential-like
|
|
100
|
+
* name) to the audit sink as they are. Off by default: they are replaced
|
|
101
|
+
* with `"[redacted]"`, because audit logs usually land in a less protected
|
|
102
|
+
* store than the table they describe.
|
|
103
|
+
*/
|
|
104
|
+
auditSecrets?: boolean;
|
|
52
105
|
/**
|
|
53
106
|
* Invoked when the audit sink throws (Story 54.6 hardening, retro
|
|
54
107
|
* 2026-06-01). The mutation has already committed, so this is a
|
|
@@ -65,6 +118,18 @@ export interface ResourceOptions<TEntity> {
|
|
|
65
118
|
* the inferred defaults.
|
|
66
119
|
*/
|
|
67
120
|
formFields?: Readonly<Record<string, FormFieldOverride>>;
|
|
121
|
+
/** Columns of the list page. */
|
|
122
|
+
list?: ResourceViewOptions;
|
|
123
|
+
/** Columns of the show page. */
|
|
124
|
+
show?: ResourceViewOptions;
|
|
125
|
+
/**
|
|
126
|
+
* The columns a create/edit may set, and the fields the form shows. When
|
|
127
|
+
* omitted: every column except the framework-managed ones, secrets
|
|
128
|
+
* (`serializeAs: null` or a credential-like name) and `formFields` marked
|
|
129
|
+
* `hidden`. A secret listed here is write-only: the form renders it empty
|
|
130
|
+
* and an empty submission keeps the stored value.
|
|
131
|
+
*/
|
|
132
|
+
editable?: ReadonlyArray<string>;
|
|
68
133
|
}
|
|
69
134
|
export interface Resource<TEntity = unknown> {
|
|
70
135
|
/** The entity class passed in. */
|
|
@@ -77,9 +142,17 @@ export interface Resource<TEntity = unknown> {
|
|
|
77
142
|
readonly actions: ReadonlyArray<ResourceAction>;
|
|
78
143
|
/** Optional audit sink (Story 54.6). */
|
|
79
144
|
readonly audit?: AuditSink;
|
|
145
|
+
/** Whether audit snapshots keep secret column values. */
|
|
146
|
+
readonly auditSecrets: boolean;
|
|
80
147
|
/** Optional audit-failure observability hook (Story 54.6 hardening). */
|
|
81
148
|
readonly onAuditError?: (event: AuditEvent, error: unknown) => void;
|
|
82
149
|
/** Frozen per-field overrides for the inferred form (Story 54.5). */
|
|
83
150
|
readonly formFields: Readonly<Record<string, FormFieldOverride>>;
|
|
151
|
+
/** Frozen list-page options. */
|
|
152
|
+
readonly list: Readonly<ResourceViewOptions>;
|
|
153
|
+
/** Frozen show-page options. */
|
|
154
|
+
readonly show: Readonly<ResourceViewOptions>;
|
|
155
|
+
/** Frozen editable allow-list; undefined means the default set. */
|
|
156
|
+
readonly editable?: ReadonlyArray<string>;
|
|
84
157
|
}
|
|
85
158
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,CAAC;AAE7E,eAAO,MAAM,gBAAgB,EAAE,aAAa,CAAC,cAAc,CAMzD,CAAC;AAEH;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IAC1B,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACpD,QAAQ,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACnD,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;CAClB;AAED,MAAM,MAAM,SAAS,GAAG,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAEpE;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IACjC
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/views/form.d.ts
CHANGED
|
@@ -39,6 +39,12 @@ export interface FormPageInput {
|
|
|
39
39
|
values?: Readonly<Record<string, unknown>>;
|
|
40
40
|
/** Validation errors keyed by column propertyKey. */
|
|
41
41
|
errors?: Readonly<Record<string, string>>;
|
|
42
|
+
/**
|
|
43
|
+
* Fields rendered empty whatever their stored or submitted value (secrets).
|
|
44
|
+
* A `password` input is always treated this way: a credential, even a hash,
|
|
45
|
+
* is never shipped back inside the page.
|
|
46
|
+
*/
|
|
47
|
+
writeOnly?: ReadonlySet<string>;
|
|
42
48
|
/**
|
|
43
49
|
* Whether the host has a CSRF token in the per-request store. When true the
|
|
44
50
|
* template emits `{{ csrfField() }}`; the handler derives it from
|
package/dist/views/form.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"form.d.ts","sourceRoot":"","sources":["../../src/views/form.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAQ/D,KAAK,SAAS,GAAG,WAAW,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC,CAAC;AAE7D,MAAM,WAAW,aAAa;IAC7B,QAAQ,EAAE,QAAQ,CAAC;IACnB,OAAO,EAAE,aAAa,CAAC,cAAc,CAAC,CAAC;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,mDAAmD;IACnD,GAAG,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACxC;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC3C,qDAAqD;IACrD,MAAM,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC1C;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,+DAA+D;AAC/D,MAAM,WAAW,SAAS;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,SAAS,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,OAAO,CAAC;IACxB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACd;AAKD,MAAM,MAAM,aAAa,GAAG;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,OAAO,CAAC;IACrB,MAAM,EAAE,SAAS,EAAE,CAAC;CACpB,CAAC;AAEF,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,aAAa,GAAG,aAAa,
|
|
1
|
+
{"version":3,"file":"form.d.ts","sourceRoot":"","sources":["../../src/views/form.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAQ/D,KAAK,SAAS,GAAG,WAAW,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC,CAAC;AAE7D,MAAM,WAAW,aAAa;IAC7B,QAAQ,EAAE,QAAQ,CAAC;IACnB,OAAO,EAAE,aAAa,CAAC,cAAc,CAAC,CAAC;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,mDAAmD;IACnD,GAAG,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACxC;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC3C,qDAAqD;IACrD,MAAM,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC1C;;;;OAIG;IACH,SAAS,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAChC;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,+DAA+D;AAC/D,MAAM,WAAW,SAAS;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,SAAS,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,OAAO,CAAC;IACxB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACd;AAKD,MAAM,MAAM,aAAa,GAAG;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,OAAO,CAAC;IACrB,MAAM,EAAE,SAAS,EAAE,CAAC;CACpB,CAAC;AAEF,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,aAAa,GAAG,aAAa,CAiDtE"}
|
package/dist/views/form.js
CHANGED
|
@@ -25,7 +25,7 @@ const SKIPPED_COLUMN_NAMES = new Set([
|
|
|
25
25
|
"deleted_at",
|
|
26
26
|
]);
|
|
27
27
|
export function buildFormViewModel(input) {
|
|
28
|
-
const { resource, columns, pkColumn, row, values, errors, csrfEnabled } = input;
|
|
28
|
+
const { resource, columns, pkColumn, row, values, errors, csrfEnabled, writeOnly, } = input;
|
|
29
29
|
const isEdit = row !== undefined;
|
|
30
30
|
const slug = encodeURIComponent(resource.name);
|
|
31
31
|
const id = isEdit ? String(row[pkColumn] ?? "") : "";
|
|
@@ -41,7 +41,7 @@ export function buildFormViewModel(input) {
|
|
|
41
41
|
: ["New ", resource.label].join("");
|
|
42
42
|
const fields = columns
|
|
43
43
|
.filter((c) => !shouldSkipColumn(c, pkColumn, resource.formFields[c.propertyKey]))
|
|
44
|
-
.map((c) => buildField(c, values ?? row, errors, resource.formFields[c.propertyKey]));
|
|
44
|
+
.map((c) => buildField(c, values ?? row, errors, resource.formFields[c.propertyKey], writeOnly?.has(c.propertyKey) === true));
|
|
45
45
|
return {
|
|
46
46
|
title: heading,
|
|
47
47
|
heading,
|
|
@@ -53,10 +53,10 @@ export function buildFormViewModel(input) {
|
|
|
53
53
|
fields,
|
|
54
54
|
};
|
|
55
55
|
}
|
|
56
|
-
function buildField(c, source, errors, override) {
|
|
56
|
+
function buildField(c, source, errors, override, writeOnly) {
|
|
57
57
|
const inputType = override?.inputType ?? inferInputType(c);
|
|
58
58
|
const name = c.propertyKey;
|
|
59
|
-
const rawValue = source?.[name];
|
|
59
|
+
const rawValue = writeOnly || inputType === "password" ? undefined : source?.[name];
|
|
60
60
|
const isCheckbox = inputType === "checkbox";
|
|
61
61
|
const value = rawValue === undefined || rawValue === null ? "" : String(rawValue);
|
|
62
62
|
return {
|
package/dist/views/form.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"form.js","sourceRoot":"","sources":["../../src/views/form.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAKH,MAAM,oBAAoB,GAAwB,IAAI,GAAG,CAAC;IACzD,YAAY;IACZ,YAAY;IACZ,YAAY;CACZ,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"form.js","sourceRoot":"","sources":["../../src/views/form.ts"],"names":[],"mappings":"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"}
|
package/dist/views/login.d.ts
CHANGED
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
*
|
|
8
8
|
* Pure `(input) => LoginViewModel` builder (Story 57.3): every value reaches
|
|
9
9
|
* HTML through `templates/login.inker`'s `{{ }}` auto-escape (the retired
|
|
10
|
-
* `escape.ts` no longer runs here)
|
|
11
|
-
*
|
|
10
|
+
* `escape.ts` no longer runs here). `error` only ever carries a message
|
|
11
|
+
* Station produced; the handler never reads it from the URL. The CSRF hidden input is emitted by
|
|
12
12
|
* inker's canonical `{{ csrfField() }}` helper, guarded by the precomputed
|
|
13
13
|
* `csrfEnabled` boolean.
|
|
14
14
|
*/
|
package/dist/views/login.js
CHANGED
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
*
|
|
8
8
|
* Pure `(input) => LoginViewModel` builder (Story 57.3): every value reaches
|
|
9
9
|
* HTML through `templates/login.inker`'s `{{ }}` auto-escape (the retired
|
|
10
|
-
* `escape.ts` no longer runs here)
|
|
11
|
-
*
|
|
10
|
+
* `escape.ts` no longer runs here). `error` only ever carries a message
|
|
11
|
+
* Station produced; the handler never reads it from the URL. The CSRF hidden input is emitted by
|
|
12
12
|
* inker's canonical `{{ csrfField() }}` helper, guarded by the precomputed
|
|
13
13
|
* `csrfEnabled` boolean.
|
|
14
14
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@c9up/station",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.16",
|
|
4
4
|
"description": "Station — admin scaffolding for the Ream framework. Declarative resource catalogue (defineResource) backing list/show/create/edit/destroy routes, audit, policies.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|