@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.
@@ -19,7 +19,8 @@
19
19
  */
20
20
  import "./augmentations.js";
21
21
  import type { ColumnMetadata } from "@c9up/atlas";
22
- import type { Resource } from "./types.js";
22
+ import { type StationLoginRateLimitConfig } from "./loginLimiter.js";
23
+ import type { Resource, SecurityAuditSink } from "./types.js";
23
24
  /**
24
25
  * Duck-typed slice of the host's IoC container — Station MUST stay
25
26
  * publishable without importing `@c9up/ream` directly (memory
@@ -99,11 +100,23 @@ export interface StationConfig {
99
100
  */
100
101
  requireAuth?: boolean;
101
102
  /**
102
- * Role required to pass the auth gate. When omitted, any
103
- * authenticated user can access `/admin/*` (the per-action
104
- * `<resource>.<action>` permission gate still applies).
103
+ * Role required to pass the auth gate, on top of {@link accessPermission}.
105
104
  */
106
105
  requireRole?: string;
106
+ /**
107
+ * Namespace of every admin permission: actions are gated behind
108
+ * `<prefix>.<resource>.<action>` (e.g. `station.users.edit`) and entry
109
+ * behind `<prefix>.access`. Defaults to `"station"`, so a grant the
110
+ * application made for its own features (`users.edit`) never opens the
111
+ * admin.
112
+ */
113
+ permissionPrefix?: string;
114
+ /**
115
+ * Permission every request must hold to enter `/admin/*`, checked before
116
+ * the per-action one. Defaults to `<permissionPrefix>.access`. `false`
117
+ * removes this gate (the per-action permissions still apply).
118
+ */
119
+ accessPermission?: string | false;
107
120
  /**
108
121
  * Where to redirect on a failed auth check. Defaults to
109
122
  * `/admin/login`.
@@ -114,6 +127,29 @@ export interface StationConfig {
114
127
  * to avoid colliding with app-level session cookies.
115
128
  */
116
129
  cookieName?: string;
130
+ /**
131
+ * `Secure` flag of the auth cookie. Defaults to on everywhere except a
132
+ * development/test process served over plain HTTP, so an unknown
133
+ * environment behaves like production.
134
+ */
135
+ cookieSecure?: boolean;
136
+ /**
137
+ * Brute-force throttle on `POST /admin/login`: 5 attempts per IP and per
138
+ * identifier every 15 minutes by default, in this process's memory. Pass
139
+ * `limiter` (warden's `AuthRateLimiter` fits) to share counts across
140
+ * instances. `false` turns it off — only for an app that throttles the
141
+ * route itself (see {@link middleware}).
142
+ */
143
+ loginRateLimit?: StationLoginRateLimitConfig | false;
144
+ /** Named router middleware attached to every route Station mounts. */
145
+ middleware?: ReadonlyArray<string>;
146
+ /**
147
+ * Sink for the admin's security events: sign-in success, failure and
148
+ * throttling, logout, authorization denials and CSRF blocks, each with the
149
+ * client IP and request id. Write events keep going to each resource's
150
+ * own `audit`.
151
+ */
152
+ audit?: SecurityAuditSink;
117
153
  }
118
154
  /** @internal Reset module-level flags between tests. */
119
155
  export declare function resetStationProviderFlags(): void;
@@ -130,9 +166,9 @@ export declare function resourcesNeedValidation(resources: ReadonlyArray<Resourc
130
166
  * Derive a `@c9up/rune` validation schema (57.7) from an entity's writable
131
167
  * column metadata — the structural replacement for the hand-rolled
132
168
  * `filterWritableBody`. The mass-assignment guarantee is now INHERENT:
133
- * `schema.validateResult()` returns only declared-column keys, so unknown body keys
134
- * (`role`, `passwordHash`, PK, timestamps) are dropped automatically — no
135
- * explicit filtering pass.
169
+ * `schema.validateResult()` returns only the keys of the editable columns it
170
+ * was given, so any other body key — an unknown one, a column outside the
171
+ * allow-list, the PK, a timestamp — is dropped automatically.
136
172
  *
137
173
  * Excluded, exactly as the old guard did: the primary key, framework-managed
138
174
  * timestamps (both the Lucid-style `autoManaged` flag AND the `created_at /
@@ -153,10 +189,13 @@ export declare function resourcesNeedValidation(resources: ReadonlyArray<Resourc
153
189
  * Returns the built schema plus the set of boolean columns — the handler
154
190
  * default-fills an ABSENT boolean key to `false` before validating (an
155
191
  * unchecked checkbox submits nothing; this preserves the old edit-clears-box
156
- * behaviour).
192
+ * behaviour). `columns` is the editable allow-list; framework-owned columns
193
+ * are dropped here too, so no caller can make them writable. `updateSchema`
194
+ * differs only for `writeOnly` columns, which an edit may leave out.
157
195
  */
158
- export declare function deriveWritableSchema(columns: ReadonlyArray<ColumnMetadata>, pkColumn: string, autoManaged: ReadonlySet<string>, excludedProps: ReadonlySet<string>, rune: RuneModule): {
196
+ export declare function deriveWritableSchema(columns: ReadonlyArray<ColumnMetadata>, pkColumn: string, autoManaged: ReadonlySet<string>, excludedProps: ReadonlySet<string>, rune: RuneModule, writeOnly?: ReadonlySet<string>): {
159
197
  schema: RuneSchema;
198
+ updateSchema: RuneSchema;
160
199
  booleanKeys: ReadonlySet<string>;
161
200
  };
162
201
  /**
@@ -165,9 +204,10 @@ export declare function deriveWritableSchema(columns: ReadonlyArray<ColumnMetada
165
204
  * preserving the old `filterWritableBody` checkbox semantics, then runs rune's
166
205
  * synchronous, never-throwing `validateResult()`. On success `result.data` holds only
167
206
  * declared-column keys (mass-assignment inherent). Exported for the unit tests
168
- * that pin the coercion CRUX.
207
+ * that pin the coercion CRUX. A blank `writeOnly` value counts as not
208
+ * submitted: the form never pre-fills those, so blank means "unchanged".
169
209
  */
170
- export declare function validateWritableBody(schema: RuneSchema, booleanKeys: ReadonlySet<string>, body: Record<string, unknown>): RuneValidationResult;
210
+ export declare function validateWritableBody(schema: RuneSchema, booleanKeys: ReadonlySet<string>, body: Record<string, unknown>, writeOnly?: ReadonlySet<string>): RuneValidationResult;
171
211
  export default class StationProvider {
172
212
  #private;
173
213
  protected app: StationAppContext;
@@ -1 +1 @@
1
- {"version":3,"file":"StationProvider.d.ts","sourceRoot":"","sources":["../src/StationProvider.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"StationProvider.d.ts","sourceRoot":"","sources":["../src/StationProvider.ts"],"names":[],"mappings":"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"}