@actuate-media/cms-core 0.86.0 → 0.88.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/CHANGELOG.md +37 -0
- package/dist/api/handler-factory.d.ts.map +1 -1
- package/dist/api/handler-factory.js +27 -2
- package/dist/api/handler-factory.js.map +1 -1
- package/dist/api/route-helpers.d.ts.map +1 -1
- package/dist/api/route-helpers.js +21 -2
- package/dist/api/route-helpers.js.map +1 -1
- package/dist/api/routes/ai-settings.d.ts.map +1 -1
- package/dist/api/routes/ai-settings.js +60 -3
- package/dist/api/routes/ai-settings.js.map +1 -1
- package/dist/api/routes/auth.d.ts.map +1 -1
- package/dist/api/routes/auth.js +48 -11
- package/dist/api/routes/auth.js.map +1 -1
- package/dist/api/routes/media.d.ts.map +1 -1
- package/dist/api/routes/media.js +3 -0
- package/dist/api/routes/media.js.map +1 -1
- package/dist/api/routes/webhooks.d.ts.map +1 -1
- package/dist/api/routes/webhooks.js +22 -1
- package/dist/api/routes/webhooks.js.map +1 -1
- package/dist/db/model-types.d.ts +3 -0
- package/dist/db/model-types.d.ts.map +1 -1
- package/dist/middleware.d.ts.map +1 -1
- package/dist/middleware.js +5 -0
- package/dist/middleware.js.map +1 -1
- package/dist/next/script-tags.d.ts.map +1 -1
- package/dist/next/script-tags.js +1 -1
- package/dist/next/script-tags.js.map +1 -1
- package/dist/script-tags/index.d.ts +1 -1
- package/dist/script-tags/index.d.ts.map +1 -1
- package/dist/script-tags/index.js +1 -1
- package/dist/script-tags/index.js.map +1 -1
- package/dist/script-tags/resolve.d.ts +27 -1
- package/dist/script-tags/resolve.d.ts.map +1 -1
- package/dist/script-tags/resolve.js +64 -2
- package/dist/script-tags/resolve.js.map +1 -1
- package/dist/security/audit.d.ts +7 -0
- package/dist/security/audit.d.ts.map +1 -1
- package/dist/security/audit.js +21 -0
- package/dist/security/audit.js.map +1 -1
- package/dist/security/center/gather.d.ts +8 -0
- package/dist/security/center/gather.d.ts.map +1 -1
- package/dist/security/center/gather.js +72 -17
- package/dist/security/center/gather.js.map +1 -1
- package/dist/security/center/index.d.ts +2 -2
- package/dist/security/center/index.d.ts.map +1 -1
- package/dist/security/center/index.js +1 -1
- package/dist/security/center/index.js.map +1 -1
- package/dist/security/center/settings.d.ts +18 -8
- package/dist/security/center/settings.d.ts.map +1 -1
- package/dist/security/center/settings.js +98 -1
- package/dist/security/center/settings.js.map +1 -1
- package/dist/security/center/types.d.ts +17 -2
- package/dist/security/center/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/prisma/migrations/0005_script_tag_delivery_controls/migration.sql +8 -0
- package/prisma/schema.prisma +16 -10
|
@@ -46,6 +46,47 @@ export async function getStoredSecuritySettings(db) {
|
|
|
46
46
|
return parseSecuritySettings({});
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
|
+
// ── Cached policy reads for hot paths (audit logging, per-request allowlist) ──
|
|
50
|
+
//
|
|
51
|
+
// Keyed by DB instance (WeakMap) so tests and multi-tenant boots that swap the
|
|
52
|
+
// client never see another instance's policy. A short TTL keeps enforcement
|
|
53
|
+
// near-real-time; `invalidateSecuritySettingsCache()` makes saves immediate
|
|
54
|
+
// within the same process.
|
|
55
|
+
const SETTINGS_CACHE_TTL_MS = 30_000;
|
|
56
|
+
const settingsCache = new WeakMap();
|
|
57
|
+
let cacheGeneration = 0;
|
|
58
|
+
export async function getCachedSecuritySettings(db) {
|
|
59
|
+
if (!db || typeof db !== 'object')
|
|
60
|
+
return parseSecuritySettings({});
|
|
61
|
+
const cached = settingsCache.get(db);
|
|
62
|
+
if (cached && cached.gen === cacheGeneration && Date.now() - cached.at < SETTINGS_CACHE_TTL_MS) {
|
|
63
|
+
return cached.value;
|
|
64
|
+
}
|
|
65
|
+
const value = await getStoredSecuritySettings(db);
|
|
66
|
+
settingsCache.set(db, { value, at: Date.now(), gen: cacheGeneration });
|
|
67
|
+
return value;
|
|
68
|
+
}
|
|
69
|
+
export function invalidateSecuritySettingsCache() {
|
|
70
|
+
cacheGeneration++;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Effective IP allowlist: the union of the config `admin.ipAllowlist` and the
|
|
74
|
+
* database-stored `security.access.ipAllowlist`. Either source being non-empty
|
|
75
|
+
* turns enforcement on. Uses the cached policy read — safe on hot paths.
|
|
76
|
+
*/
|
|
77
|
+
export async function getEffectiveIpAllowlist(db) {
|
|
78
|
+
const config = getActuateConfig();
|
|
79
|
+
const configRanges = Array.isArray(config?.admin?.ipAllowlist)
|
|
80
|
+
? config.admin.ipAllowlist
|
|
81
|
+
: [];
|
|
82
|
+
const settings = await getCachedSecuritySettings(db);
|
|
83
|
+
const union = [...configRanges];
|
|
84
|
+
for (const entry of settings.access.ipAllowlist) {
|
|
85
|
+
if (!union.includes(entry))
|
|
86
|
+
union.push(entry);
|
|
87
|
+
}
|
|
88
|
+
return union;
|
|
89
|
+
}
|
|
49
90
|
export async function getSecurityCenterData(opts) {
|
|
50
91
|
const d = opts.db;
|
|
51
92
|
const isProduction = isProductionEnv();
|
|
@@ -108,19 +149,34 @@ export async function getSecurityCenterData(opts) {
|
|
|
108
149
|
apiKeysHashed: true,
|
|
109
150
|
webhookSecretsEncrypted: encryptionKey === 'pass',
|
|
110
151
|
};
|
|
111
|
-
// ── IP allowlist (config
|
|
112
|
-
const
|
|
152
|
+
// ── IP allowlist (config ∪ database; enforced per-request) ───────────────────
|
|
153
|
+
const configRanges = Array.isArray(config?.admin?.ipAllowlist)
|
|
113
154
|
? config.admin.ipAllowlist
|
|
114
155
|
: [];
|
|
156
|
+
const dbRanges = settings.access.ipAllowlist;
|
|
157
|
+
const ranges = [...configRanges];
|
|
158
|
+
for (const entry of dbRanges) {
|
|
159
|
+
if (!ranges.includes(entry))
|
|
160
|
+
ranges.push(entry);
|
|
161
|
+
}
|
|
115
162
|
const currentIp = opts.currentIp ?? null;
|
|
163
|
+
const allowlistSource = configRanges.length > 0 && dbRanges.length > 0
|
|
164
|
+
? 'mixed'
|
|
165
|
+
: configRanges.length > 0
|
|
166
|
+
? 'config'
|
|
167
|
+
: dbRanges.length > 0
|
|
168
|
+
? 'database'
|
|
169
|
+
: 'none';
|
|
116
170
|
const ipAllowlist = {
|
|
117
171
|
enabled: ranges.length > 0,
|
|
118
|
-
source:
|
|
172
|
+
source: allowlistSource,
|
|
119
173
|
ranges,
|
|
174
|
+
configRanges,
|
|
120
175
|
currentIp,
|
|
121
176
|
currentIpAllowed: ranges.length > 0 && currentIp ? isIpAllowed(currentIp, ranges) : null,
|
|
122
177
|
};
|
|
123
|
-
const sessionMaxAgeHours =
|
|
178
|
+
const sessionMaxAgeHours = settings.session.timeoutHours;
|
|
179
|
+
const auditEnabled = settings.access.auditLoggingEnabled;
|
|
124
180
|
const status = computeSecurityStatus({
|
|
125
181
|
isProduction,
|
|
126
182
|
settings,
|
|
@@ -132,23 +188,22 @@ export async function getSecurityCenterData(opts) {
|
|
|
132
188
|
activeSessions,
|
|
133
189
|
csrfEnabled: true,
|
|
134
190
|
uploadValidation: true,
|
|
135
|
-
auditEnabled
|
|
191
|
+
auditEnabled,
|
|
136
192
|
});
|
|
137
193
|
const editable = { source: 'database', editable: true };
|
|
138
194
|
const sources = {
|
|
139
195
|
mfaRequired: editable,
|
|
140
196
|
mfaGracePeriodDays: editable,
|
|
141
197
|
maxConcurrentSessions: editable,
|
|
142
|
-
sessionMaxAgeHours:
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
},
|
|
198
|
+
sessionMaxAgeHours: editable,
|
|
199
|
+
idleLogout: editable,
|
|
200
|
+
ipAllowlist: configRanges.length > 0
|
|
201
|
+
? {
|
|
202
|
+
source: 'database',
|
|
203
|
+
editable: true,
|
|
204
|
+
reason: 'Config ranges from admin.ipAllowlist are always enforced and merged with this list.',
|
|
205
|
+
}
|
|
206
|
+
: editable,
|
|
152
207
|
csrf: { source: 'computed', editable: false, reason: 'Always enabled for mutating requests.' },
|
|
153
208
|
rateLimiting: {
|
|
154
209
|
source: 'environment',
|
|
@@ -162,7 +217,7 @@ export async function getSecurityCenterData(opts) {
|
|
|
162
217
|
},
|
|
163
218
|
cmsSecret: { source: 'environment', editable: false },
|
|
164
219
|
encryptionKey: { source: 'environment', editable: false },
|
|
165
|
-
audit:
|
|
220
|
+
audit: editable,
|
|
166
221
|
};
|
|
167
222
|
return {
|
|
168
223
|
settings,
|
|
@@ -175,7 +230,7 @@ export async function getSecurityCenterData(opts) {
|
|
|
175
230
|
activeSessions,
|
|
176
231
|
csrfEnabled: true,
|
|
177
232
|
uploadValidation: true,
|
|
178
|
-
auditEnabled
|
|
233
|
+
auditEnabled,
|
|
179
234
|
sessionMaxAgeHours,
|
|
180
235
|
viewerHasMfa,
|
|
181
236
|
environment: process.env.VERCEL_ENV ?? process.env.NODE_ENV ?? 'development',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gather.js","sourceRoot":"","sources":["../../../src/security/center/gather.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"gather.js","sourceRoot":"","sources":["../../../src/security/center/gather.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
* them without pulling in server-side DB/env code. The async gatherer
|
|
7
7
|
* (`gather.ts`) is imported directly by the API handlers, not re-exported here.
|
|
8
8
|
*/
|
|
9
|
-
export type { ApiKeysSecuritySummary, CheckStatus, IpAllowlistStatus, MfaSettings, SecretsStatus, SecurityCenterData, SecurityCheck, SecuritySettings, SecuritySourceMetadata, SecurityStatus, SecurityStatusInput, SecurityStatusLevel, SecurityWarning, SecurityWarningCategory, SessionSettings, UsersSecuritySummary, } from './types.js';
|
|
10
|
-
export { DEFAULT_SECURITY_SETTINGS, MAX_CONCURRENT_SESSION_OPTIONS, MFA_GRACE_PERIOD_OPTIONS, mfaEnableLockoutError, parseSecuritySettings, validateIpRange, validateSecuritySettings, type SecurityValidationIssue, } from './settings.js';
|
|
9
|
+
export type { AccessSettings, ApiKeysSecuritySummary, CheckStatus, IpAllowlistStatus, MfaSettings, SecretsStatus, SecurityCenterData, SecurityCheck, SecuritySettings, SecuritySourceMetadata, SecurityStatus, SecurityStatusInput, SecurityStatusLevel, SecurityWarning, SecurityWarningCategory, SessionSettings, UsersSecuritySummary, } from './types.js';
|
|
10
|
+
export { DEFAULT_SECURITY_SETTINGS, DEFAULT_SESSION_TIMEOUT_HOURS, MAX_CONCURRENT_SESSION_OPTIONS, MAX_IP_ALLOWLIST_ENTRIES, MFA_GRACE_PERIOD_OPTIONS, SESSION_TIMEOUT_HOURS_OPTIONS, ipAllowlistLockoutError, mfaEnableLockoutError, parseSecuritySettings, validateIpRange, validateSecuritySettings, type SecurityValidationIssue, } from './settings.js';
|
|
11
11
|
export { computeSecurityStatus } from './status.js';
|
|
12
12
|
export { summarizeApiKeys, summarizeUsers, type ApiKeyRow, type UserRow } from './summaries.js';
|
|
13
13
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/security/center/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,YAAY,EACV,sBAAsB,EACtB,WAAW,EACX,iBAAiB,EACjB,WAAW,EACX,aAAa,EACb,kBAAkB,EAClB,aAAa,EACb,gBAAgB,EAChB,sBAAsB,EACtB,cAAc,EACd,mBAAmB,EACnB,mBAAmB,EACnB,eAAe,EACf,uBAAuB,EACvB,eAAe,EACf,oBAAoB,GACrB,MAAM,YAAY,CAAA;AAEnB,OAAO,EACL,yBAAyB,EACzB,8BAA8B,EAC9B,wBAAwB,EACxB,qBAAqB,EACrB,qBAAqB,EACrB,eAAe,EACf,wBAAwB,EACxB,KAAK,uBAAuB,GAC7B,MAAM,eAAe,CAAA;AAEtB,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AAEnD,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,KAAK,SAAS,EAAE,KAAK,OAAO,EAAE,MAAM,gBAAgB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/security/center/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,YAAY,EACV,cAAc,EACd,sBAAsB,EACtB,WAAW,EACX,iBAAiB,EACjB,WAAW,EACX,aAAa,EACb,kBAAkB,EAClB,aAAa,EACb,gBAAgB,EAChB,sBAAsB,EACtB,cAAc,EACd,mBAAmB,EACnB,mBAAmB,EACnB,eAAe,EACf,uBAAuB,EACvB,eAAe,EACf,oBAAoB,GACrB,MAAM,YAAY,CAAA;AAEnB,OAAO,EACL,yBAAyB,EACzB,6BAA6B,EAC7B,8BAA8B,EAC9B,wBAAwB,EACxB,wBAAwB,EACxB,6BAA6B,EAC7B,uBAAuB,EACvB,qBAAqB,EACrB,qBAAqB,EACrB,eAAe,EACf,wBAAwB,EACxB,KAAK,uBAAuB,GAC7B,MAAM,eAAe,CAAA;AAEtB,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AAEnD,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,KAAK,SAAS,EAAE,KAAK,OAAO,EAAE,MAAM,gBAAgB,CAAA"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { DEFAULT_SECURITY_SETTINGS, MAX_CONCURRENT_SESSION_OPTIONS, MFA_GRACE_PERIOD_OPTIONS, mfaEnableLockoutError, parseSecuritySettings, validateIpRange, validateSecuritySettings, } from './settings.js';
|
|
1
|
+
export { DEFAULT_SECURITY_SETTINGS, DEFAULT_SESSION_TIMEOUT_HOURS, MAX_CONCURRENT_SESSION_OPTIONS, MAX_IP_ALLOWLIST_ENTRIES, MFA_GRACE_PERIOD_OPTIONS, SESSION_TIMEOUT_HOURS_OPTIONS, ipAllowlistLockoutError, mfaEnableLockoutError, parseSecuritySettings, validateIpRange, validateSecuritySettings, } from './settings.js';
|
|
2
2
|
export { computeSecurityStatus } from './status.js';
|
|
3
3
|
export { summarizeApiKeys, summarizeUsers } from './summaries.js';
|
|
4
4
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/security/center/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/security/center/index.ts"],"names":[],"mappings":"AA4BA,OAAO,EACL,yBAAyB,EACzB,6BAA6B,EAC7B,8BAA8B,EAC9B,wBAAwB,EACxB,wBAAwB,EACxB,6BAA6B,EAC7B,uBAAuB,EACvB,qBAAqB,EACrB,qBAAqB,EACrB,eAAe,EACf,wBAAwB,GAEzB,MAAM,eAAe,CAAA;AAEtB,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AAEnD,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAgC,MAAM,gBAAgB,CAAA"}
|
|
@@ -1,15 +1,12 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Security settings parsing + validation (pure).
|
|
3
|
-
*
|
|
4
|
-
* The persisted, enforced policy lives under the `security` key of the
|
|
5
|
-
* `settings` global. Only fields the runtime actually enforces are stored
|
|
6
|
-
* here (MFA requirement + grace, concurrent-session cap) so the UI never
|
|
7
|
-
* presents a control that does nothing.
|
|
8
|
-
*/
|
|
9
1
|
import type { SecuritySettings } from './types.js';
|
|
2
|
+
export declare const DEFAULT_SESSION_TIMEOUT_HOURS = 168;
|
|
10
3
|
export declare const DEFAULT_SECURITY_SETTINGS: SecuritySettings;
|
|
11
4
|
export declare const MFA_GRACE_PERIOD_OPTIONS: readonly [0, 1, 7, 14, 30];
|
|
12
5
|
export declare const MAX_CONCURRENT_SESSION_OPTIONS: readonly [0, 3, 5, 10];
|
|
6
|
+
/** Design contract: 1 hour / 8 hours / 24 hours / 7 days. */
|
|
7
|
+
export declare const SESSION_TIMEOUT_HOURS_OPTIONS: readonly [1, 8, 24, 168];
|
|
8
|
+
/** Upper bound on stored allowlist entries — enough for real fleets, bounded against abuse. */
|
|
9
|
+
export declare const MAX_IP_ALLOWLIST_ENTRIES = 100;
|
|
13
10
|
export interface SecurityValidationIssue {
|
|
14
11
|
field: string;
|
|
15
12
|
message: string;
|
|
@@ -19,6 +16,19 @@ export interface SecurityValidationIssue {
|
|
|
19
16
|
export declare function parseSecuritySettings(blob: unknown): SecuritySettings;
|
|
20
17
|
/** Validate an incoming settings payload. Pure — no DB / lockout checks here. */
|
|
21
18
|
export declare function validateSecuritySettings(settings: SecuritySettings): SecurityValidationIssue[];
|
|
19
|
+
/**
|
|
20
|
+
* Lockout-safe IP allowlist check. Saving a non-empty allowlist that does not
|
|
21
|
+
* include the acting admin's own IP would cut them off on the very next
|
|
22
|
+
* request. Callers MUST run this server-side (with the union of DB + config
|
|
23
|
+
* ranges) and only bypass it when the request explicitly confirms the risk.
|
|
24
|
+
* Returns `null` when the save is safe.
|
|
25
|
+
*/
|
|
26
|
+
export declare function ipAllowlistLockoutError(input: {
|
|
27
|
+
/** Effective ranges being enforced after the save (DB entries ∪ config entries). */
|
|
28
|
+
effectiveAllowlist: string[];
|
|
29
|
+
/** Resolved client IP of the request, or null/'unknown' when unresolvable. */
|
|
30
|
+
currentIp: string | null;
|
|
31
|
+
}): string | null;
|
|
22
32
|
/**
|
|
23
33
|
* Lockout-safe MFA enable check. Enabling org-wide MFA while the acting admin
|
|
24
34
|
* has no TOTP configured would lock them (and possibly everyone) out. Callers
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../../src/security/center/settings.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../../src/security/center/settings.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAElD,eAAO,MAAM,6BAA6B,MAAM,CAAA;AAEhD,eAAO,MAAM,yBAAyB,EAAE,gBAQvC,CAAA;AAED,eAAO,MAAM,wBAAwB,4BAA6B,CAAA;AAClE,eAAO,MAAM,8BAA8B,wBAAyB,CAAA;AACpE,6DAA6D;AAC7D,eAAO,MAAM,6BAA6B,0BAA2B,CAAA;AACrE,+FAA+F;AAC/F,eAAO,MAAM,wBAAwB,MAAM,CAAA;AAE3C,MAAM,WAAW,uBAAuB;IACtC,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAA;CAC9B;AAOD,kFAAkF;AAClF,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,OAAO,GAAG,gBAAgB,CA2CrE;AAwCD,iFAAiF;AACjF,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,gBAAgB,GAAG,uBAAuB,EAAE,CA2C9F;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE;IAC7C,oFAAoF;IACpF,kBAAkB,EAAE,MAAM,EAAE,CAAA;IAC5B,8EAA8E;IAC9E,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CACzB,GAAG,MAAM,GAAG,IAAI,CAShB;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE;IAC3C,QAAQ,EAAE,OAAO,CAAA;IACjB,YAAY,EAAE,OAAO,CAAA;IACrB,WAAW,EAAE,MAAM,CAAA;CACpB,GAAG,MAAM,GAAG,IAAI,CAMhB;AAKD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAatD"}
|
|
@@ -1,9 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Security settings parsing + validation (pure).
|
|
3
|
+
*
|
|
4
|
+
* The persisted, enforced policy lives under the `security` key of the
|
|
5
|
+
* `settings` global. Only fields the runtime actually enforces are stored
|
|
6
|
+
* here (MFA requirement + grace, concurrent-session cap) so the UI never
|
|
7
|
+
* presents a control that does nothing.
|
|
8
|
+
*/
|
|
9
|
+
import { isIpAllowed } from '../ip-allowlist.js';
|
|
10
|
+
export const DEFAULT_SESSION_TIMEOUT_HOURS = 168;
|
|
1
11
|
export const DEFAULT_SECURITY_SETTINGS = {
|
|
2
12
|
mfa: { required: false, gracePeriodDays: 7 },
|
|
3
|
-
session: {
|
|
13
|
+
session: {
|
|
14
|
+
maxConcurrentSessions: 5,
|
|
15
|
+
timeoutHours: DEFAULT_SESSION_TIMEOUT_HOURS,
|
|
16
|
+
idleLogoutEnabled: false,
|
|
17
|
+
},
|
|
18
|
+
access: { ipAllowlist: [], auditLoggingEnabled: true },
|
|
4
19
|
};
|
|
5
20
|
export const MFA_GRACE_PERIOD_OPTIONS = [0, 1, 7, 14, 30];
|
|
6
21
|
export const MAX_CONCURRENT_SESSION_OPTIONS = [0, 3, 5, 10];
|
|
22
|
+
/** Design contract: 1 hour / 8 hours / 24 hours / 7 days. */
|
|
23
|
+
export const SESSION_TIMEOUT_HOURS_OPTIONS = [1, 8, 24, 168];
|
|
24
|
+
/** Upper bound on stored allowlist entries — enough for real fleets, bounded against abuse. */
|
|
25
|
+
export const MAX_IP_ALLOWLIST_ENTRIES = 100;
|
|
7
26
|
function toInt(value, fallback) {
|
|
8
27
|
const n = typeof value === 'number' ? value : Number(value);
|
|
9
28
|
return Number.isFinite(n) ? Math.trunc(n) : fallback;
|
|
@@ -16,6 +35,7 @@ export function parseSecuritySettings(blob) {
|
|
|
16
35
|
: {});
|
|
17
36
|
const mfa = (sec.mfa && typeof sec.mfa === 'object' ? sec.mfa : {});
|
|
18
37
|
const session = (sec.session && typeof sec.session === 'object' ? sec.session : {});
|
|
38
|
+
const access = (sec.access && typeof sec.access === 'object' ? sec.access : {});
|
|
19
39
|
return {
|
|
20
40
|
mfa: {
|
|
21
41
|
required: Boolean(mfa.required),
|
|
@@ -24,11 +44,46 @@ export function parseSecuritySettings(blob) {
|
|
|
24
44
|
},
|
|
25
45
|
session: {
|
|
26
46
|
maxConcurrentSessions: clampSessions(toInt(session.maxConcurrentSessions, DEFAULT_SECURITY_SETTINGS.session.maxConcurrentSessions)),
|
|
47
|
+
timeoutHours: snapTimeoutHours(session.timeoutHours),
|
|
48
|
+
idleLogoutEnabled: Boolean(session.idleLogoutEnabled),
|
|
49
|
+
},
|
|
50
|
+
access: {
|
|
51
|
+
ipAllowlist: toStringList(access.ipAllowlist),
|
|
52
|
+
// Default ON — only an explicit `false` disables audit logging.
|
|
53
|
+
auditLoggingEnabled: access.auditLoggingEnabled !== false,
|
|
27
54
|
},
|
|
28
55
|
updatedAt: typeof sec.updatedAt === 'string' ? sec.updatedAt : undefined,
|
|
29
56
|
updatedBy: typeof sec.updatedBy === 'string' ? sec.updatedBy : undefined,
|
|
30
57
|
};
|
|
31
58
|
}
|
|
59
|
+
/** Snap an arbitrary value onto the allowed timeout options; invalid ⇒ default (7 days). */
|
|
60
|
+
function snapTimeoutHours(value) {
|
|
61
|
+
const n = toInt(value, DEFAULT_SESSION_TIMEOUT_HOURS);
|
|
62
|
+
return SESSION_TIMEOUT_HOURS_OPTIONS.includes(n)
|
|
63
|
+
? n
|
|
64
|
+
: DEFAULT_SESSION_TIMEOUT_HOURS;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Coerce an allowlist blob into trimmed, de-duplicated strings. Invalid
|
|
68
|
+
* IP/CIDR entries are kept so {@link validateSecuritySettings} can report them
|
|
69
|
+
* back to the caller instead of silently dropping them.
|
|
70
|
+
*/
|
|
71
|
+
function toStringList(value) {
|
|
72
|
+
if (!Array.isArray(value))
|
|
73
|
+
return [];
|
|
74
|
+
const out = [];
|
|
75
|
+
for (const entry of value) {
|
|
76
|
+
if (typeof entry !== 'string')
|
|
77
|
+
continue;
|
|
78
|
+
const trimmed = entry.trim();
|
|
79
|
+
if (!trimmed || out.includes(trimmed))
|
|
80
|
+
continue;
|
|
81
|
+
out.push(trimmed);
|
|
82
|
+
if (out.length >= MAX_IP_ALLOWLIST_ENTRIES)
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
return out;
|
|
86
|
+
}
|
|
32
87
|
function clampGrace(n) {
|
|
33
88
|
if (n < 0)
|
|
34
89
|
return 0;
|
|
@@ -62,8 +117,50 @@ export function validateSecuritySettings(settings) {
|
|
|
62
117
|
severity: 'error',
|
|
63
118
|
});
|
|
64
119
|
}
|
|
120
|
+
const timeout = settings.session.timeoutHours;
|
|
121
|
+
if (!SESSION_TIMEOUT_HOURS_OPTIONS.includes(timeout)) {
|
|
122
|
+
issues.push({
|
|
123
|
+
field: 'timeoutHours',
|
|
124
|
+
message: 'Session timeout must be 1 hour, 8 hours, 24 hours, or 7 days.',
|
|
125
|
+
severity: 'error',
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
const allowlist = settings.access.ipAllowlist;
|
|
129
|
+
if (allowlist.length > MAX_IP_ALLOWLIST_ENTRIES) {
|
|
130
|
+
issues.push({
|
|
131
|
+
field: 'ipAllowlist',
|
|
132
|
+
message: `The IP allowlist supports at most ${MAX_IP_ALLOWLIST_ENTRIES} entries.`,
|
|
133
|
+
severity: 'error',
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
const invalidEntries = allowlist.filter((entry) => !validateIpRange(entry));
|
|
137
|
+
if (invalidEntries.length > 0) {
|
|
138
|
+
issues.push({
|
|
139
|
+
field: 'ipAllowlist',
|
|
140
|
+
message: `Invalid IP or CIDR entries: ${invalidEntries.join(', ')}`,
|
|
141
|
+
severity: 'error',
|
|
142
|
+
});
|
|
143
|
+
}
|
|
65
144
|
return issues;
|
|
66
145
|
}
|
|
146
|
+
/**
|
|
147
|
+
* Lockout-safe IP allowlist check. Saving a non-empty allowlist that does not
|
|
148
|
+
* include the acting admin's own IP would cut them off on the very next
|
|
149
|
+
* request. Callers MUST run this server-side (with the union of DB + config
|
|
150
|
+
* ranges) and only bypass it when the request explicitly confirms the risk.
|
|
151
|
+
* Returns `null` when the save is safe.
|
|
152
|
+
*/
|
|
153
|
+
export function ipAllowlistLockoutError(input) {
|
|
154
|
+
if (input.effectiveAllowlist.length === 0)
|
|
155
|
+
return null;
|
|
156
|
+
if (!input.currentIp || input.currentIp === 'unknown') {
|
|
157
|
+
return 'Your IP address could not be determined, so this allowlist may lock you out. Confirm to save anyway.';
|
|
158
|
+
}
|
|
159
|
+
if (!isIpAllowed(input.currentIp, input.effectiveAllowlist)) {
|
|
160
|
+
return `Your current IP (${input.currentIp}) is not in the allowlist — saving would lock you out. Add it, or confirm to save anyway.`;
|
|
161
|
+
}
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
67
164
|
/**
|
|
68
165
|
* Lockout-safe MFA enable check. Enabling org-wide MFA while the acting admin
|
|
69
166
|
* has no TOTP configured would lock them (and possibly everyone) out. Callers
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings.js","sourceRoot":"","sources":["../../../src/security/center/settings.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"settings.js","sourceRoot":"","sources":["../../../src/security/center/settings.ts"],"names":[],"mappings":"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"}
|
|
@@ -49,10 +49,22 @@ export interface MfaSettings {
|
|
|
49
49
|
/** Persisted, enforced session policy. `maxConcurrentSessions = 0` ⇒ unlimited. */
|
|
50
50
|
export interface SessionSettings {
|
|
51
51
|
maxConcurrentSessions: number;
|
|
52
|
+
/** Session lifetime in hours (1 | 8 | 24 | 168). Login mints JWT + row expiry from this. */
|
|
53
|
+
timeoutHours: number;
|
|
54
|
+
/** When true, the admin client signs the user out after `timeoutHours` of inactivity. */
|
|
55
|
+
idleLogoutEnabled: boolean;
|
|
56
|
+
}
|
|
57
|
+
/** Persisted, enforced access-control policy. */
|
|
58
|
+
export interface AccessSettings {
|
|
59
|
+
/** IP/CIDR entries merged with the config `admin.ipAllowlist` (union) at enforcement time. */
|
|
60
|
+
ipAllowlist: string[];
|
|
61
|
+
/** When false, `logEvent()` no-ops except for security-critical events. Default true. */
|
|
62
|
+
auditLoggingEnabled: boolean;
|
|
52
63
|
}
|
|
53
64
|
export interface SecuritySettings {
|
|
54
65
|
mfa: MfaSettings;
|
|
55
66
|
session: SessionSettings;
|
|
67
|
+
access: AccessSettings;
|
|
56
68
|
updatedAt?: string;
|
|
57
69
|
updatedBy?: string;
|
|
58
70
|
}
|
|
@@ -80,8 +92,11 @@ export interface SecretsStatus {
|
|
|
80
92
|
}
|
|
81
93
|
export interface IpAllowlistStatus {
|
|
82
94
|
enabled: boolean;
|
|
83
|
-
source: 'config' | 'none';
|
|
95
|
+
source: 'config' | 'database' | 'mixed' | 'none';
|
|
96
|
+
/** Effective enforced ranges — the union of config + database entries. */
|
|
84
97
|
ranges: string[];
|
|
98
|
+
/** Ranges provided by `admin.ipAllowlist` in actuate.config.ts (read-only). */
|
|
99
|
+
configRanges: string[];
|
|
85
100
|
currentIp: string | null;
|
|
86
101
|
currentIpAllowed: boolean | null;
|
|
87
102
|
}
|
|
@@ -103,7 +118,7 @@ export interface SecurityCenterData {
|
|
|
103
118
|
csrfEnabled: boolean;
|
|
104
119
|
uploadValidation: boolean;
|
|
105
120
|
auditEnabled: boolean;
|
|
106
|
-
/** Effective max session age in hours
|
|
121
|
+
/** Effective max session age in hours — mirrors `settings.session.timeoutHours`. */
|
|
107
122
|
sessionMaxAgeHours: number;
|
|
108
123
|
/** Whether the current admin (the viewer) has TOTP enabled — drives lockout-safe MFA enable. */
|
|
109
124
|
viewerHasMfa: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/security/center/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,MAAM,mBAAmB,GAAG,QAAQ,GAAG,iBAAiB,GAAG,SAAS,GAAG,SAAS,CAAA;AACtF,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAAA;AAEjE,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,WAAW,CAAA;IACnB,4DAA4D;IAC5D,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,uEAAuE;IACvE,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,MAAM,uBAAuB,GAC/B,MAAM,GACN,UAAU,GACV,UAAU,GACV,SAAS,GACT,YAAY,GACZ,OAAO,GACP,SAAS,GACT,QAAQ,CAAA;AAEZ,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAA;IACV,QAAQ,EAAE,UAAU,GAAG,SAAS,GAAG,MAAM,CAAA;IACzC,QAAQ,EAAE,uBAAuB,CAAA;IACjC,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,mBAAmB,CAAA;IAC3B,wEAAwE;IACxE,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,aAAa,EAAE,CAAA;IACvB,QAAQ,EAAE,eAAe,EAAE,CAAA;IAC3B,aAAa,EAAE,MAAM,CAAA;CACtB;AAED,sCAAsC;AACtC,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,OAAO,CAAA;IACjB,eAAe,EAAE,MAAM,CAAA;IACvB,oFAAoF;IACpF,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,mFAAmF;AACnF,MAAM,WAAW,eAAe;IAC9B,qBAAqB,EAAE,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/security/center/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
-- Design-parity delivery controls for script tags:
|
|
2
|
+
-- loadAsync — inject `async` into external <script src> tags at resolve time
|
|
3
|
+
-- disableInPreview — skip the tag when rendering inside CMS preview mode
|
|
4
|
+
-- consentCategory — cookie-consent gate (none | analytics | marketing | functional | preferences)
|
|
5
|
+
ALTER TABLE "actuate_script_tags"
|
|
6
|
+
ADD COLUMN "loadAsync" BOOLEAN NOT NULL DEFAULT false,
|
|
7
|
+
ADD COLUMN "disableInPreview" BOOLEAN NOT NULL DEFAULT true,
|
|
8
|
+
ADD COLUMN "consentCategory" TEXT NOT NULL DEFAULT 'none';
|
package/prisma/schema.prisma
CHANGED
|
@@ -867,16 +867,22 @@ model Invite {
|
|
|
867
867
|
}
|
|
868
868
|
|
|
869
869
|
model ScriptTag {
|
|
870
|
-
id
|
|
871
|
-
name
|
|
872
|
-
code
|
|
873
|
-
placement
|
|
874
|
-
scope
|
|
875
|
-
targetPaths
|
|
876
|
-
priority
|
|
877
|
-
enabled
|
|
878
|
-
|
|
879
|
-
|
|
870
|
+
id String @id @default(cuid())
|
|
871
|
+
name String
|
|
872
|
+
code String @db.Text
|
|
873
|
+
placement String
|
|
874
|
+
scope String
|
|
875
|
+
targetPaths String[]
|
|
876
|
+
priority Int @default(100)
|
|
877
|
+
enabled Boolean @default(true)
|
|
878
|
+
/// Inject `async` into external <script src> tags so they don't block render.
|
|
879
|
+
loadAsync Boolean @default(false)
|
|
880
|
+
/// Skip this tag when the page is rendered inside CMS preview mode.
|
|
881
|
+
disableInPreview Boolean @default(true)
|
|
882
|
+
/// Cookie-consent category gate: none | analytics | marketing | functional | preferences.
|
|
883
|
+
consentCategory String @default("none")
|
|
884
|
+
createdAt DateTime @default(now())
|
|
885
|
+
updatedAt DateTime @updatedAt
|
|
880
886
|
|
|
881
887
|
@@index([enabled])
|
|
882
888
|
@@index([placement])
|