Skip to content

Commit 605e190

Browse files
os-zhuangclaude
andauthored
feat(spec)!: prune still-dead aspirational config from Theme / Translation / Webhook (#3494) (#3516)
* feat(spec)!: prune still-dead aspirational config from Theme / Translation / Webhook (#3494) Removes the authorable-but-never-consumed props confirmed dead by the 2026-06 liveness audit (follow-up to #1878/#1893; same enforce-or-remove treatment as #2377/#3464): - Theme: spacing, breakpoints, logo, density, wcagContrast, rtl, touchTarget, keyboardNavigation (+ SpacingSchema, BreakpointsSchema, DensityModeSchema, WcagContrastLevelSchema and their aliases/types) — the objectui theme engine never emitted or consumed them. - Translation: fileOrganization, messageFormat, lazyLoad, cache (+ MessageFormatSchema, TranslationFileOrganizationSchema) — no ICU engine exists; interpolation is always simple substitution. - Webhook: body, payloadFields, includeSession, authentication (non-HMAC; HMAC via secret stays), retryPolicy, tags + the entire inbound WebhookReceiverSchema — the delivery path sends a fixed envelope and the outbox owns its own retry schedule. Liveness ledger entries for the removed props are dropped (dead->live flip for materialized props stays with #3490). Kept deliberately: supportedLocales (live pinyin-search reader), job retryPolicy/timeout (being built in the follow-up PR), and all webhook props materialized by the #3489 bridge. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * test(cli): drop lint assertions for the pruned webhook authentication/retryPolicy props The liveness compile lint no longer warns on authentication — the prop (and its ledger entry) were removed outright, so the experimental-marker test case is obsolete; the showcase-shaped fixture loses its dead retryPolicy key. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Jack Zhuang <277994282+os-zhuang@users.noreply.github.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
1 parent cb8322e commit 605e190

31 files changed

Lines changed: 140 additions & 985 deletions

File tree

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
---
2+
"@objectstack/spec": minor
3+
---
4+
5+
feat(spec)!: prune the still-dead aspirational config from Theme / Translation / Webhook (#3494)
6+
7+
Removes the authorable-but-never-consumed props confirmed dead by the 2026-06
8+
liveness audit (follow-up to #1878/#1893; same treatment as the #2377 and
9+
#3464 prunes). Authoring any of these was a silent no-op.
10+
11+
## Removed
12+
13+
**Theme** (`ThemeSchema`) — the theme engine (objectui `generateThemeVars`)
14+
never emitted or consumed them:
15+
- Props: `spacing`, `breakpoints`, `logo`, `density`, `wcagContrast`, `rtl`,
16+
`touchTarget`, `keyboardNavigation`
17+
- Exports: `SpacingSchema`, `BreakpointsSchema`, `DensityModeSchema` (+
18+
deprecated `DensityMode` alias), `WcagContrastLevelSchema` (+ deprecated
19+
`WcagContrastLevel` alias), and the `Spacing` / `Breakpoints` /
20+
`DensityMode` / `WcagContrastLevel` types
21+
22+
**Translation** (`TranslationConfigSchema`) — no runtime reader; there is no
23+
ICU engine and interpolation is always simple `{variable}` substitution:
24+
- Props: `fileOrganization`, `messageFormat`, `lazyLoad`, `cache`
25+
- Exports: `MessageFormatSchema`, `TranslationFileOrganizationSchema`, and the
26+
`MessageFormat` / `TranslationFileOrganization` types
27+
28+
**Webhook** (`WebhookSchema`) — the delivery path always sends its own fixed
29+
envelope and only applies HMAC signing via `secret`; delivery retries are owned
30+
by the messaging outbox's fixed schedule:
31+
- Props: `body`, `payloadFields`, `includeSession`, `authentication`
32+
(bearer/basic/api-key were never attached; HMAC via `secret` stays),
33+
`retryPolicy`, `tags`
34+
- Exports: the entire inbound `WebhookReceiverSchema` + `WebhookReceiver` type
35+
(never consumed by any runtime)
36+
37+
## Migration
38+
39+
Delete these keys from your configs — they never did anything, so removing
40+
them changes no behavior. Parsed output no longer contains the previously
41+
defaulted keys (`includeSession: false`, `fileOrganization: 'per_locale'`,
42+
`messageFormat: 'simple'`, `lazyLoad: false`, `cache: true`). Webhook HMAC
43+
signing (`secret`), `headers`, and `timeoutMs` are unaffected. File layout for
44+
translations remains a pure authoring convention — no config knob needed.
45+
46+
## Deliberately NOT removed
47+
48+
- Translation `supportedLocales` — it has a live reader (pinyin-search
49+
capability toggle in `serve.ts`).
50+
- Job `retryPolicy` / `timeout` — being implemented (built, not pruned) in the
51+
#3494 follow-up PR.
52+
- The materialized webhook props (`name`, `object`, `triggers`, `url`,
53+
`method`, `headers`, `timeoutMs`, `secret`, `isActive`, `description`,
54+
`label`) — live via the #3489 bridge; ledger flip tracked in #3490.
55+
56+
Refs #3494, #1878, #1893.

content/docs/automation/webhooks.mdx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -514,7 +514,7 @@ Four phases. Each phase delivers visible user value.
514514
> `system/*` Zod schemas. There is no `system/webhook-delivery.zod.ts` and no
515515
> `SysWebhookSchema` / `SysWebhookDeliverySchema` /
516516
> `WebhookSignatureHeaderSchema` / `WebhookEventPayloadSchema`. Instead it
517-
> reused the existing `WebhookSchema` (and `WebhookReceiverSchema`) in
517+
> reused the existing `WebhookSchema` in
518518
> `automation/webhook.zod.ts`, defined `sys_webhook` as an
519519
> `ObjectSchema.create()` in the plugin, and reused
520520
> service-messaging's `sys_http_delivery` outbox for deliveries (ADR-0018 M3).
@@ -555,8 +555,9 @@ Four phases. Each phase delivers visible user value.
555555
## 16. Non-goals (v1)
556556

557557
- **Inbound webhooks.** Receiving HTTP from third parties is a separate
558-
protocol (`WebhookReceiverSchema` already exists). The two systems
559-
share no runtime.
558+
protocol (the aspirational `WebhookReceiverSchema` was removed unbuilt in
559+
#3494 — reintroduce it only alongside a real inbound runtime). The two
560+
systems share no runtime.
560561
- **Webhook chaining / fan-in.** No "if receiver returns a payload,
561562
emit a new event". Out of scope.
562563
- **GraphQL subscriptions / WebSocket fan-out.** Different transport,

content/docs/getting-started/quick-reference.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ Flows, state machines, approvals, and integrations.
157157
| **[Flow](/docs/references/automation/flow)** | `flow.zod.ts` | Flow, FlowNode | Visual workflow builder |
158158
| **[Approval](/docs/references/automation/approval)** | `approval.zod.ts` | ApprovalNodeConfig | Flow approval-node config |
159159
| **[State Machine](/docs/references/automation/state-machine)** | `state-machine.zod.ts` | StateMachine | State machine definitions |
160-
| **[Webhook](/docs/references/automation/webhook)** | `webhook.zod.ts` | Webhook, WebhookReceiver | Outbound webhooks |
160+
| **[Webhook](/docs/references/automation/webhook)** | `webhook.zod.ts` | Webhook | Outbound webhooks |
161161
| **[ETL](/docs/references/automation/etl)** | `etl.zod.ts` | ETLPipeline | Data transformation pipelines |
162162
| **[Trigger Registry](/docs/references/automation/trigger-registry)** | `trigger-registry.zod.ts` | TriggerRegistry | Event-driven triggers |
163163
| **[Sync](/docs/references/automation/sync)** | `sync.zod.ts` | DataSyncConfig, SyncMode | Bi-directional data sync |

content/docs/protocol/kernel/i18n-standard.mdx

Lines changed: 3 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -322,10 +322,8 @@ const label = i18n.t('account.fields.unknown', 'en');
322322
<Callout type="warn">
323323
**Design intent.** Automatic CLDR plural selection (the `key` / `key_plural`
324324
convention) is not yet implemented by the file adapter — `t()` performs only
325-
`{{param}}` interpolation. To pluralize today, set `messageFormat: 'icu'` and
326-
author ICU MessageFormat strings (see
327-
[Use ICU MessageFormat](#4-use-icu-messageformat-for-complex-messages) below),
328-
or select the form in application code.
325+
`{{param}}` interpolation. To pluralize today, select the plural form in
326+
application code before calling `t()`.
329327
</Callout>
330328

331329
```typescript
@@ -855,15 +853,7 @@ export default defineStack({
855853
}
856854
```
857855

858-
### 4. Use ICU MessageFormat for Complex Messages
859-
860-
```json
861-
{
862-
"accountStatus": "{count, plural, =0 {No accounts} =1 {One account} other {# accounts}}"
863-
}
864-
```
865-
866-
### 5. Test All Locales
856+
### 4. Test All Locales
867857

868858
```typescript
869859
// ✓ GOOD: Test with actual locales
@@ -891,18 +881,6 @@ export default defineStack({
891881
// Fallback chain
892882
fallbackLocale: 'en',
893883

894-
// File organization: 'bundled' | 'per_locale' | 'per_namespace' (default 'per_locale')
895-
fileOrganization: 'per_locale',
896-
897-
// Message format: 'simple' {variable} interpolation (default) | 'icu' MessageFormat
898-
messageFormat: 'simple',
899-
900-
// Load translations on demand? (default false)
901-
lazyLoad: true,
902-
903-
// Cache translations? (default true)
904-
cache: true,
905-
906884
// Translation service — design intent, not yet a recognized config key
907885
// translationService: {
908886
// provider: 'google-translate',

content/docs/references/automation/webhook.mdx

Lines changed: 2 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ value that silently never fires.
4646
## TypeScript Usage
4747

4848
```typescript
49-
import { Webhook, WebhookReceiver, WebhookTriggerType } from '@objectstack/spec/automation';
50-
import type { Webhook, WebhookReceiver, WebhookTriggerType } from '@objectstack/spec/automation';
49+
import { Webhook, WebhookTriggerType } from '@objectstack/spec/automation';
50+
import type { Webhook, WebhookTriggerType } from '@objectstack/spec/automation';
5151

5252
// Validate data
5353
const result = Webhook.parse(data);
@@ -68,32 +68,10 @@ const result = Webhook.parse(data);
6868
| **url** | `string` || External webhook endpoint URL |
6969
| **method** | `Enum<'GET' \| 'POST' \| 'PUT' \| 'PATCH' \| 'DELETE'>` || HTTP method |
7070
| **headers** | `Record<string, string>` | optional | Custom HTTP headers |
71-
| **body** | `any` | optional | Request body payload (if not using default record data) |
72-
| **payloadFields** | `string[]` | optional | Fields to include. Empty = All |
73-
| **includeSession** | `boolean` || Include user session info |
74-
| **authentication** | `{ type: Enum<'none' \| 'bearer' \| 'basic' \| 'api-key'>; credentials?: Record<string, string> }` | optional | Authentication configuration. [EXPERIMENTAL — not enforced] The webhook delivery path only applies HMAC signing via `secret`; bearer/basic/api-key credentials are not attached to outbound requests yet (liveness audit #1878/#1893). |
75-
| **retryPolicy** | `{ maxRetries: integer; backoffStrategy: Enum<'exponential' \| 'linear' \| 'fixed'>; initialDelayMs: integer; maxDelayMs: integer }` | optional | Retry policy configuration |
7671
| **timeoutMs** | `integer` || Request timeout in milliseconds |
7772
| **secret** | `string` | optional | Signing secret for HMAC signature verification |
7873
| **isActive** | `boolean` || Whether webhook is active |
7974
| **description** | `string` | optional | Webhook description |
80-
| **tags** | `string[]` | optional | Tags for organization |
81-
82-
83-
---
84-
85-
## WebhookReceiver
86-
87-
### Properties
88-
89-
| Property | Type | Required | Description |
90-
| :--- | :--- | :--- | :--- |
91-
| **name** | `string` || Webhook receiver unique name (lowercase snake_case) |
92-
| **path** | `string` || URL Path (e.g. /webhooks/stripe) |
93-
| **verificationType** | `Enum<'none' \| 'header_token' \| 'hmac' \| 'ip_whitelist'>` || |
94-
| **verificationParams** | `{ header?: string; secret?: string; ips?: string[] }` | optional | |
95-
| **action** | `Enum<'trigger_flow' \| 'script' \| 'upsert_record'>` || |
96-
| **target** | `string` || Flow ID or Script name |
9775

9876

9977
---

content/docs/references/integration/connector.mdx

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -470,16 +470,10 @@ Synchronization strategy
470470
| **url** | `string` || External webhook endpoint URL |
471471
| **method** | `Enum<'GET' \| 'POST' \| 'PUT' \| 'PATCH' \| 'DELETE'>` || HTTP method |
472472
| **headers** | `Record<string, string>` | optional | Custom HTTP headers |
473-
| **body** | `any` | optional | Request body payload (if not using default record data) |
474-
| **payloadFields** | `string[]` | optional | Fields to include. Empty = All |
475-
| **includeSession** | `boolean` || Include user session info |
476-
| **authentication** | `{ type: Enum<'none' \| 'bearer' \| 'basic' \| 'api-key'>; credentials?: Record<string, string> }` | optional | Authentication configuration. [EXPERIMENTAL — not enforced] The webhook delivery path only applies HMAC signing via `secret`; bearer/basic/api-key credentials are not attached to outbound requests yet (liveness audit #1878/#1893). |
477-
| **retryPolicy** | `{ maxRetries: integer; backoffStrategy: Enum<'exponential' \| 'linear' \| 'fixed'>; initialDelayMs: integer; maxDelayMs: integer }` | optional | Retry policy configuration |
478473
| **timeoutMs** | `integer` || Request timeout in milliseconds |
479474
| **secret** | `string` | optional | Signing secret for HMAC signature verification |
480475
| **isActive** | `boolean` || Whether webhook is active |
481476
| **description** | `string` | optional | Webhook description |
482-
| **tags** | `string[]` | optional | Tags for organization |
483477
| **events** | `Enum<'record.created' \| 'record.updated' \| 'record.deleted' \| 'sync.started' \| 'sync.completed' \| 'sync.failed' \| 'auth.expired' \| 'rate_limit.exceeded'>[]` | optional | Connector events to subscribe to (not yet enforced — no runtime dispatches these; see #3197) |
484478
| **signatureAlgorithm** | `Enum<'hmac_sha256' \| 'hmac_sha512' \| 'none'>` || Webhook signature algorithm |
485479

content/docs/references/integration/meta.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
"connector",
66
"connector-auth",
77
"mapping",
8-
"translation",
98
"---Transport & Storage---",
109
"http",
1110
"message-queue",

content/docs/references/integration/misc.mdx

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ description: Misc protocol schemas
1212
## TypeScript Usage
1313

1414
```typescript
15-
import { AckMode, ApiVersionConfig, BuildConfig, CdcConfig, DatabaseConnector, DatabasePoolConfig, DatabaseTable, DeliveryGuarantee, DeploymentConfig, DlqConfig, DomainConfig, EdgeFunctionConfig, EnvironmentVariables, FileAccessPattern, FileFilterConfig, FileMetadataConfig, FileStorageConnector, FileStorageProvider, FileVersioningConfig, GitHubActionsWorkflow, GitHubCommitConfig, GitHubConnector, GitHubIssueTracking, GitHubProvider, GitHubPullRequestConfig, GitHubReleaseConfig, GitHubRepository, GitRepositoryConfig, MessageQueueConnector, ProducerConfig, SaasConnector, SaasObjectType, SaasProvider, SslConfig, StorageBucket, TopicQueue, VercelConnector, VercelFramework, VercelMonitoring, VercelProject, VercelProvider, VercelTeam } from '@objectstack/spec/integration';
16-
import type { AckMode, ApiVersionConfig, BuildConfig, CdcConfig, DatabaseConnector, DatabasePoolConfig, DatabaseTable, DeliveryGuarantee, DeploymentConfig, DlqConfig, DomainConfig, EdgeFunctionConfig, EnvironmentVariables, FileAccessPattern, FileFilterConfig, FileMetadataConfig, FileStorageConnector, FileStorageProvider, FileVersioningConfig, GitHubActionsWorkflow, GitHubCommitConfig, GitHubConnector, GitHubIssueTracking, GitHubProvider, GitHubPullRequestConfig, GitHubReleaseConfig, GitHubRepository, GitRepositoryConfig, MessageQueueConnector, ProducerConfig, SaasConnector, SaasObjectType, SaasProvider, SslConfig, StorageBucket, TopicQueue, VercelConnector, VercelFramework, VercelMonitoring, VercelProject, VercelProvider, VercelTeam } from '@objectstack/spec/integration';
15+
import { AckMode, ApiVersionConfig, BuildConfig, CdcConfig, DatabaseConnector, DatabasePoolConfig, DatabaseTable, DeliveryGuarantee, DeploymentConfig, DlqConfig, DomainConfig, EdgeFunctionConfig, EnvironmentVariables, FileAccessPattern, FileFilterConfig, FileMetadataConfig, FileStorageConnector, FileStorageProvider, FileVersioningConfig, GitHubActionsWorkflow, GitHubCommitConfig, GitHubConnector, GitHubIssueTracking, GitHubProvider, GitHubPullRequestConfig, GitHubReleaseConfig, GitHubRepository, GitRepositoryConfig, MessageFormat, MessageQueueConnector, ProducerConfig, SaasConnector, SaasObjectType, SaasProvider, SslConfig, StorageBucket, TopicQueue, VercelConnector, VercelFramework, VercelMonitoring, VercelProject, VercelProvider, VercelTeam } from '@objectstack/spec/integration';
16+
import type { AckMode, ApiVersionConfig, BuildConfig, CdcConfig, DatabaseConnector, DatabasePoolConfig, DatabaseTable, DeliveryGuarantee, DeploymentConfig, DlqConfig, DomainConfig, EdgeFunctionConfig, EnvironmentVariables, FileAccessPattern, FileFilterConfig, FileMetadataConfig, FileStorageConnector, FileStorageProvider, FileVersioningConfig, GitHubActionsWorkflow, GitHubCommitConfig, GitHubConnector, GitHubIssueTracking, GitHubProvider, GitHubPullRequestConfig, GitHubReleaseConfig, GitHubRepository, GitRepositoryConfig, MessageFormat, MessageQueueConnector, ProducerConfig, SaasConnector, SaasObjectType, SaasProvider, SslConfig, StorageBucket, TopicQueue, VercelConnector, VercelFramework, VercelMonitoring, VercelProject, VercelProvider, VercelTeam } from '@objectstack/spec/integration';
1717

1818
// Validate data
1919
const result = AckMode.parse(data);
@@ -527,6 +527,22 @@ GitHub provider type
527527
| **autoDeployPreview** | `boolean` || Auto-deploy preview branches |
528528

529529

530+
---
531+
532+
## MessageFormat
533+
534+
Message format/serialization
535+
536+
### Allowed Values
537+
538+
* `json`
539+
* `xml`
540+
* `protobuf`
541+
* `avro`
542+
* `text`
543+
* `binary`
544+
545+
530546
---
531547

532548
## MessageQueueConnector

content/docs/references/integration/translation.mdx

Lines changed: 0 additions & 39 deletions
This file was deleted.

content/docs/references/system/translation.mdx

Lines changed: 2 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ Translation data for a single field.
1616
## TypeScript Usage
1717

1818
```typescript
19-
import { ActionResultDialogTranslation, AppTranslationBundle, CoverageBreakdownEntry, FieldTranslation, Locale, MessageFormat, ObjectTranslationData, ObjectTranslationNode, TranslationBundle, TranslationConfig, TranslationCoverageResult, TranslationData, TranslationDiffItem, TranslationDiffStatus, TranslationFileOrganization } from '@objectstack/spec/system';
20-
import type { ActionResultDialogTranslation, AppTranslationBundle, CoverageBreakdownEntry, FieldTranslation, Locale, MessageFormat, ObjectTranslationData, ObjectTranslationNode, TranslationBundle, TranslationConfig, TranslationCoverageResult, TranslationData, TranslationDiffItem, TranslationDiffStatus, TranslationFileOrganization } from '@objectstack/spec/system';
19+
import { ActionResultDialogTranslation, AppTranslationBundle, CoverageBreakdownEntry, FieldTranslation, Locale, ObjectTranslationData, ObjectTranslationNode, TranslationBundle, TranslationConfig, TranslationCoverageResult, TranslationData, TranslationDiffItem, TranslationDiffStatus } from '@objectstack/spec/system';
20+
import type { ActionResultDialogTranslation, AppTranslationBundle, CoverageBreakdownEntry, FieldTranslation, Locale, ObjectTranslationData, ObjectTranslationNode, TranslationBundle, TranslationConfig, TranslationCoverageResult, TranslationData, TranslationDiffItem, TranslationDiffStatus } from '@objectstack/spec/system';
2121

2222
// Validate data
2323
const result = ActionResultDialogTranslation.parse(data);
@@ -99,18 +99,6 @@ Translation data for a single field
9999
---
100100

101101

102-
---
103-
104-
## MessageFormat
105-
106-
Message interpolation format: ICU MessageFormat or simple `{variable}` replacement
107-
108-
### Allowed Values
109-
110-
* `icu`
111-
* `simple`
112-
113-
114102
---
115103

116104
## ObjectTranslationData
@@ -169,10 +157,6 @@ Internationalization configuration
169157
| **defaultLocale** | `string` || Default locale (e.g., "en") |
170158
| **supportedLocales** | `string[]` || Supported BCP-47 locale codes |
171159
| **fallbackLocale** | `string` | optional | Fallback locale code |
172-
| **fileOrganization** | `Enum<'bundled' \| 'per_locale' \| 'per_namespace'>` || File organization strategy |
173-
| **messageFormat** | `Enum<'icu' \| 'simple'>` || Message interpolation format (ICU MessageFormat or simple). [EXPERIMENTAL — 'icu' not enforced] No ICU MessageFormat engine is wired; messageFormat:'icu' is accepted but interpolation falls back to simple substitution (liveness audit #1878/#1893). |
174-
| **lazyLoad** | `boolean` || Load translations on demand |
175-
| **cache** | `boolean` || Cache loaded translations. [EXPERIMENTAL — not enforced] No runtime consumer reads this cache flag yet (liveness audit #1878/#1893). |
176160

177161

178162
---
@@ -252,16 +236,3 @@ Translation diff status: missing from bundle, redundant (no matching metadata),
252236

253237
---
254238

255-
## TranslationFileOrganization
256-
257-
Translation file organization strategy
258-
259-
### Allowed Values
260-
261-
* `bundled`
262-
* `per_locale`
263-
* `per_namespace`
264-
265-
266-
---
267-

0 commit comments

Comments
 (0)