Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .changeset/30209-audit-log-default-view.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
'@objectstack/plugin-audit': patch
'@objectstack/platform-objects': patch
---

fix(plugin-audit,platform-objects): the audit log's default list shows what people did, not the rows the platform writes beside it; the audit objects read in Chinese

Clause-②: no
Metadata-protocol: none

Setup's 审计日志 opens the first `sys_audit_log` list view, `recent`. One sign-in used to put two rows there (the `login` row and an `update` of the person's `sys_user` stamping `last_login_at` / `last_login_ip`), the first sign-in through the console a third (the token-signing key in `sys_jwks`), and one settings change three or four (the `config_change` row, the stored setting, a secret's ciphertext, and the settings trail's own entry).

- The ledger writer now marks the sign-in stamp row with `metadata: {"event":"auth.last_login_stamp"}`, the way `config_change` rows carry `settings.set`. Only an update of `sys_user` whose changes are the stamp's fields alone is marked; an administrator's edit of a user is not. The row is still written.
- `recent` leaves out the marked row, the rows on `sys_secret`, `sys_setting_audit`, `sys_platform_setting_audit`, `sys_jwks`, `sys_migration` and `sys_migration_journal`, and the rows on `sys_setting` / `sys_platform_setting` other than `config_change`. Nothing is removed from storage, and `all_events` (全部) still lists every row.
- `sys_platform_setting` and `sys_platform_setting_audit` were in no translation bundle, so they read English in every locale; they now ship in `@objectstack/platform-objects`' bundles with zh-CN translations (ja-JP and es-ES carry the English fill). `sys_comment_reaction`'s zh-CN bundle is translated.
15 changes: 14 additions & 1 deletion packages/platform-objects/scripts/i18n-extract.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,18 @@ import {
} from '../src/metadata/index.js';

// ── System ────────────────────────────────────────────────────────────────
import { SysSetting, SysSecret, SysSettingAudit, SysMigration, SysExchangeRate } from '../src/system/index.js';
// `SysPlatformSetting` / `SysPlatformSettingAudit` are the settings global
// rung (ADR-0131 D7). service-settings registers them, and their labels are
// served from this package's bundles like `sys_setting`'s.
import {
SysSetting,
SysPlatformSetting,
SysSecret,
SysSettingAudit,
SysPlatformSettingAudit,
SysMigration,
SysExchangeRate,
} from '../src/system/index.js';

// ── Existing Setup app + dashboards + translations ────────────────────────
import { SETUP_APP } from '../src/apps/setup.app.js';
Expand Down Expand Up @@ -316,8 +327,10 @@ const config: ObjectStackDefinition = defineStack({

// System
SysSetting,
SysPlatformSetting,
SysSecret,
SysSettingAudit,
SysPlatformSettingAudit,
SysMigration,
SysExchangeRate,
] as any,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const OWNED_OBJECTS = new Set([
// metadata (sys_view_definition retired as inert, ADR-0131 D13)
'sys_metadata', 'sys_metadata_history', 'sys_metadata_audit',
// system
'sys_setting', 'sys_secret', 'sys_setting_audit', 'sys_migration', 'sys_exchange_rate',
'sys_setting', 'sys_platform_setting', 'sys_secret', 'sys_setting_audit', 'sys_platform_setting_audit', 'sys_migration', 'sys_exchange_rate',
]);

describe('objects translation bundle ownership (ADR-0029 D8)', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3446,6 +3446,54 @@ export const enObjects: NonNullable<TranslationData['objects']> = {
}
}
},
sys_platform_setting: {
label: "Platform Setting",
pluralLabel: "Platform Settings",
description: "Deployment-wide settings values: the global rung of the settings cascade.",
fields: {
id: {
label: "Setting ID"
},
created_at: {
label: "Created At"
},
updated_at: {
label: "Updated At"
},
namespace: {
label: "Namespace",
help: "Manifest namespace (e.g. mail, storage, ai)."
},
key: {
label: "Key",
help: "Specifier key inside the namespace (snake_case)."
},
value: {
label: "Value",
help: "JSON-encoded value. Null when encrypted=true (see value_enc)."
},
encrypted: {
label: "Encrypted",
help: "When true, the value is stored encrypted-at-rest in value_enc; value column is null."
},
locked: {
label: "Locked",
help: "When true, tenant and user rows cannot override this value; writes against those scopes return 409."
},
locked_reason: {
label: "Lock Reason",
help: "Human-readable explanation surfaced in the UI tooltip when locked=true."
},
value_enc: {
label: "Encrypted Value",
help: "Handle of the sys_secret row holding the ciphertext. Set only when encrypted=true."
},
updated_by: {
label: "Updated By",
help: "Last actor who wrote this row through the settings service."
}
}
},
sys_secret: {
label: "Secret",
pluralLabel: "Secrets",
Expand Down Expand Up @@ -3573,6 +3621,84 @@ export const enObjects: NonNullable<TranslationData['objects']> = {
}
}
},
sys_platform_setting_audit: {
label: "Platform Setting Audit Entry",
pluralLabel: "Platform Setting Audit",
description: "Append-only audit trail for SettingsService mutations of global-scope keys.",
fields: {
id: {
label: "ID"
},
created_at: {
label: "Created At",
help: "When the mutation was recorded."
},
namespace: {
label: "Namespace"
},
key: {
label: "Key"
},
scope: {
label: "Scope",
help: "Cascade layer the row was written to — always the global rung here.",
options: {
global: "Global"
}
},
action: {
label: "Action",
help: "Mutation kind.",
options: {
set: "Set",
reset: "Reset",
lock: "Lock",
unlock: "Unlock",
rotate: "Rotate"
}
},
actor_id: {
label: "Actor",
help: "User who performed the mutation; null for system jobs."
},
source: {
label: "Source",
help: "Mutation entry-point.",
options: {
ui: "UI",
api: "API",
migration: "Migration",
import: "Import",
system: "System"
}
},
reason: {
label: "Reason",
help: "Free-text justification provided by the actor (optional)."
},
old_hash: {
label: "Old Hash",
help: "Digest of the previous value, never the plaintext: sha256: hex for a plain value, the keyed hmac-sha256: digest for a secret. Null when previously unset, or for a secret with no keyed digest."
},
new_hash: {
label: "New Hash",
help: "Digest of the new value, never the plaintext: sha256: hex for a plain value, the keyed hmac-sha256: digest for a secret. Null on reset, or for a secret with no keyed digest."
},
encrypted: {
label: "Encrypted",
help: "True when the field carries secret material (rotation is interesting)."
},
request_id: {
label: "Request ID",
help: "Correlates with sys_audit_log / tracing."
}
},
_views: {
recent: {
label: "Recent"
}
}
},
sys_migration: {
label: "Data Migration",
pluralLabel: "Data Migrations",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3446,6 +3446,54 @@ export const esESObjects: NonNullable<TranslationData['objects']> = {
}
}
},
sys_platform_setting: {
label: "Platform Setting",
pluralLabel: "Platform Settings",
description: "Deployment-wide settings values: the global rung of the settings cascade.",
fields: {
id: {
label: "Setting ID"
},
created_at: {
label: "Created At"
},
updated_at: {
label: "Updated At"
},
namespace: {
label: "Namespace",
help: "Manifest namespace (e.g. mail, storage, ai)."
},
key: {
label: "Key",
help: "Specifier key inside the namespace (snake_case)."
},
value: {
label: "Value",
help: "JSON-encoded value. Null when encrypted=true (see value_enc)."
},
encrypted: {
label: "Encrypted",
help: "When true, the value is stored encrypted-at-rest in value_enc; value column is null."
},
locked: {
label: "Locked",
help: "When true, tenant and user rows cannot override this value; writes against those scopes return 409."
},
locked_reason: {
label: "Lock Reason",
help: "Human-readable explanation surfaced in the UI tooltip when locked=true."
},
value_enc: {
label: "Encrypted Value",
help: "Handle of the sys_secret row holding the ciphertext. Set only when encrypted=true."
},
updated_by: {
label: "Updated By",
help: "Last actor who wrote this row through the settings service."
}
}
},
sys_secret: {
label: "Secreto",
pluralLabel: "Secretos",
Expand Down Expand Up @@ -3573,6 +3621,84 @@ export const esESObjects: NonNullable<TranslationData['objects']> = {
}
}
},
sys_platform_setting_audit: {
label: "Platform Setting Audit Entry",
pluralLabel: "Platform Setting Audit",
description: "Append-only audit trail for SettingsService mutations of global-scope keys.",
fields: {
id: {
label: "ID"
},
created_at: {
label: "Created At",
help: "When the mutation was recorded."
},
namespace: {
label: "Namespace"
},
key: {
label: "Key"
},
scope: {
label: "Scope",
help: "Cascade layer the row was written to — always the global rung here.",
options: {
global: "Global"
}
},
action: {
label: "Action",
help: "Mutation kind.",
options: {
set: "Set",
reset: "Reset",
lock: "Lock",
unlock: "Unlock",
rotate: "Rotate"
}
},
actor_id: {
label: "Actor",
help: "User who performed the mutation; null for system jobs."
},
source: {
label: "Source",
help: "Mutation entry-point.",
options: {
ui: "UI",
api: "API",
migration: "Migration",
import: "Import",
system: "System"
}
},
reason: {
label: "Reason",
help: "Free-text justification provided by the actor (optional)."
},
old_hash: {
label: "Old Hash",
help: "Digest of the previous value, never the plaintext: sha256: hex for a plain value, the keyed hmac-sha256: digest for a secret. Null when previously unset, or for a secret with no keyed digest."
},
new_hash: {
label: "New Hash",
help: "Digest of the new value, never the plaintext: sha256: hex for a plain value, the keyed hmac-sha256: digest for a secret. Null on reset, or for a secret with no keyed digest."
},
encrypted: {
label: "Encrypted",
help: "True when the field carries secret material (rotation is interesting)."
},
request_id: {
label: "Request ID",
help: "Correlates with sys_audit_log / tracing."
}
},
_views: {
recent: {
label: "Recent"
}
}
},
sys_migration: {
label: "Migración de datos",
pluralLabel: "Migraciones de datos",
Expand Down
Loading
Loading