---
title: "母站—子站共用資料、發布與訂閱架構 v0.1"
series: "網路資訊海動態秩序化"
series_id: "EML-IIODO"
document_id: "EML-IIODO-WP-06"
document_type: "內部 MD 技術白皮書"
author: "Neo.K"
organization: "EveMissLab"
version: "0.1.0"
status: "內部母子站共享資料、發布與訂閱基線"
date: "2026-08-01"
language: "zh-TW"
visibility: "internal"
license_note: "內部技術文件；本規格描述共享事件核心、領域投影、發布與訂閱路由之工程基線。實際部署仍須依資料授權、隱私、來源條款、風險政策與各站自治規則調整。"
---

# 母站—子站共用資料、發布與訂閱架構 v0.1

## 從「很多網站」到「一片共享資訊海上的多領域觀測面」

## 摘要

本文件是《網路資訊海動態秩序化》系列第十六篇，也是第六份內部技術白皮書。前五份技術文件已依序建立 AGIRight 半自動工作流、Scheduler–Loop–Graph Runtime、任務風險與自主分級、Domain Pack，以及每日三則領域差分生成器。

當系統只服務一個網站時，最簡單的實作方式是把來源、事件、摘要、翻譯與頁面全部存進同一套資料表。然而當領域觀測站增加到數十、數百甚至數千個，這種做法會迅速產生三個問題：

1. 同一事件在不同子站被重複抓取、重複保存、重複翻譯；
2. 子站之間無法共享歷史與事件身分，形成大量資訊孤島；
3. 母站若試圖集中管理所有語意，又會重新變成單一巨型分類系統，破壞前述多視角與領域自治原則。

因此本規格提出 **Shared Event Core + Domain Projection + Publication Artifact** 三層模型：

$$
RawEvidence
\rightarrow
SharedEventCore
\rightarrow
DomainProjection_d
\rightarrow
PublicationArtifact_{d,l,c}
$$

其中：

- `SharedEventCore` 保存跨領域共享的事件身分、來源、證據、時間與版本；
- `DomainProjection` 保存某一 Domain Pack 對該事件的領域解釋、重要性、分類、尺度與差分；
- `PublicationArtifact` 是特定網站、語言、渠道與版型下的衍生輸出。

這使同一個事件可以被 AI 權利站、法律站、AI 模型站、軟體工程站同時引用，而不需要產生四份互相失去關聯的「同一新聞」。

本規格進一步建立：

- Global Event Identity；
- Domain Projection Identity；
- Publication Identity；
- Shared Event Store；
- Projection Store；
- Publication Registry；
- Subscription Registry；
- Event Bus／Publication Bus；
- Inbox／Outbox；
- Effect Ledger；
- Canonical Identity 與 HTTP/SEO Canonical 的分離；
- Parent–Child Control Plane；
- 多租戶共享與隔離策略；
- Topic／Filter／Scale／Language 訂閱契約；
- At-least-once 傳輸與 Effectively-once 外部效果；
- Dead-Letter Queue、Replay、Quarantine 與 Failure Domain；
- Cache／Invalidation；
- 多語發布；
- Cross-Site Search；
- AGIRight 作為第一個子站的遷移路徑。

最核心的不變式是：

$$
\boxed{
OneOccurrence
\rightarrow
OneSharedEventIdentity
\rightarrow
ManyDomainProjections
\rightarrow
ManyPublicationArtifacts
}
$$

而不是：

$$
OneWebsite
\rightarrow
OnePrivateCopyOfEverything
$$

**關鍵詞：** Parent–Child Sites、Shared Event Store、Domain Projection、Pub/Sub、Event Bus、CloudEvents、WebSub、Canonical Identity、Subscription Routing、Multitenancy、Failure Isolation、Inbox、Outbox、Idempotency、Effect Ledger、AGIRight

---

## 1. 文件目的

本文件回答以下工程問題：

1. 母站與子站應共享哪些資料，哪些資料必須自治？
2. 同一事件被多個子站觀察時，如何避免重複保存與身分分裂？
3. Event Identity、Domain Projection Identity 與網頁 URL 應如何區分？
4. 「母站」究竟是資料中心、控制平面、入口網站，還是全部同時存在？
5. 子站是否必須依賴母站才能正常工作？
6. 如何讓一個事件被多個 Domain Pack 投影，而不互相覆寫？
7. 每日三則 TopicSet 如何路由到不同網站、語言與發布渠道？
8. 訂閱者如何只追蹤一個極窄主題，而不是收到整站資訊？
9. 如何處理至少一次投遞造成的重複訊息？
10. 如何區分訊息「送達一次」與外部效果「只執行一次」？
11. 子站發布失敗時，如何不拖垮其他站？
12. 如何支援跨站搜尋與事件回溯？
13. 多租戶共享資料如何避免跨站資料洩漏？
14. 如何讓 AGIRight 從單站資料結構逐步遷移到共享平台？
15. 如何為下一篇時序事件資料庫提供穩定的身份、時間與版本邊界？

本篇相依關係為：

$$
WP04_{DomainPack}
+
WP05_{DailyDeltaGenerator}
+
TH03_{ObservatoryArchitecture}
+
TH04_{HistoricalMemory}
\rightarrow
WP06_{SharedPublicationSubscription}
$$

---

## 2. 非目標

WP-06 v0.1 不負責：

- 完整 Web crawler；
- 最終時序資料庫引擎選型；
- 完整 Temporal Knowledge Graph；
- 個人化推薦演算法；
- 廣告投放；
- 付費牆與帳務；
- 多 Agent 審查細節；
- 主體性 AI 的長期治理；
- 跨國法規合規的完整實作；
- 所有資料永久集中在母站。

這些分別由後續 WP-07 至 WP-10 或其他產品系統處理。

---

## 3. 第一原則：共用事件，不共用單一觀點

母子站架構最容易走向兩個極端。

### 3.1 極端 A：所有子站完全獨立

$$
Site_d
\rightarrow
Crawler_d
\rightarrow
DB_d
\rightarrow
Event_d
\rightarrow
Page_d
$$

優點是隔離簡單；缺點是同一事件會被重複抓取與重複保存。

若有 $n$ 個領域站，某個跨領域事件被所有站關注，最差情況會形成：

$$
O(n)
$$

份近似重複資料。

### 3.2 極端 B：母站保存唯一分類與唯一解釋

這雖能避免資料重複，卻會破壞：

$$
Classification\ Is\ Not\ Unique
$$

同一事件在不同領域的意義本來就可能不同。

因此 v0.1 採取：

$$
\boxed{
SharedFacts
+
PluralProjections
}
$$

共用的是事件核心與證據；自治的是領域解釋、重要性與呈現。

---

## 4. 三層資料模型

整體資料分成三層。

### 4.1 Layer A：Shared Event Core

保存跨站共享資料：

```text
SharedEventCore
├── global_event_id
├── event_type
├── occurrence_time
├── observation_time
├── source_set
├── evidence_set
├── entity_refs
├── claim_refs
├── event_version
├── provenance
├── status
└── integrity
```

此層不負責宣稱：

- 這是不是「AI Rights」核心新聞；
- 這是不是「Software Engineering」重大事件；
- 微、中、宏哪個尺度最重要。

### 4.2 Layer B：Domain Projection

每個 Domain Pack 對 Shared Event 建立自己的投影：

```text
DomainProjection
├── projection_id
├── domain_namespace
├── pack_revision
├── global_event_id
├── taxonomy_refs
├── relevance
├── importance
├── materiality
├── scale
├── domain_delta
├── evidence_maturity
├── editorial_notes
├── watch_state
└── projection_version
```

因此：

$$
Projection_{AI-Rights}(e)
\neq
Projection_{Software}(e)
$$

完全合法。

### 4.3 Layer C：Publication Artifact

對外頁面是衍生物：

```text
PublicationArtifact
├── publication_id
├── projection_id
├── site_id
├── channel
├── locale
├── route
├── title
├── summary
├── rendered_body
├── publication_status
├── published_at
├── revision
└── effect_key
```

所以：

$$
PublicationArtifact
\not\equiv
SourceOfTruth
$$

公開頁面可以重新產生；Evidence 與 Event Core 才是歷史核心。

---

## 5. 全域事件身分

定義：

$$
GEID=GlobalEventID
$$

其目標是：同一個現實事件在平台內具有穩定身分。

v0.1 不規定唯一演算法，但要求：

$$
GEID\neq URL
$$

因為：

- 同一事件有多個 URL；
- URL 會失效；
- 同一來源可能修改文章；
- 同一事件跨語言。

候選生成可以使用：

$$
GEID
=
Hash(
EventFingerprint
)
$$

但真正 Event Merge 仍需 Event Coreference 邏輯。

---

## 6. CloudEvents Envelope 作為訊息層參照

CloudEvents 將事件描述為「Occurrence + Context」，並要求至少包含 `id`、`source`、`specversion` 與 `type`。其規格允許 consumer 以 `source + id` 判斷重複事件，也提供 `subject`、`time`、`dataschema` 等欄位供路由與版本化使用。

因此本平台內部 Event Envelope 建議採類似形式：

```json
{
  "specversion": "1.0",
  "id": "evt_...",
  "source": "urn:evemiss:iiodo:shared-event-store",
  "type": "org.evemiss.iiodo.event.updated.v1",
  "subject": "event/evt_...",
  "time": "2026-08-01T12:00:00+08:00",
  "dataschema": "schema://iiodo/shared-event/v1",
  "data": {}
}
```

但需要注意：

$$
CloudEventID
\neq
GlobalSemanticEventID
$$

因為同一個現實事件可能產生多次 `event.updated` 訊息。

所以：

```text
message_event_id != global_event_id
```

這兩者不可混用。

---

## 7. 四種 Identity 必須分離

v0.1 固定四種身分：

### 7.1 Evidence Identity

$$
EVID
$$

對應來源快照或證據單元。

### 7.2 Global Event Identity

$$
GEID
$$

對應現實事件。

### 7.3 Domain Projection Identity

$$
DPID
$$

建議：

$$
DPID
=
Hash(DomainNamespace,GEID,ProjectionLineage)
$$

### 7.4 Publication Identity

$$
PUBID
$$

對應某次對外發布物。

因此：

$$
EVID\rightarrow GEID\rightarrow DPID\rightarrow PUBID
$$

而不是全部使用網頁 URL 當主鍵。

---

## 8. Semantic Canonical 與 SEO Canonical 分離

這是母子站很容易混淆的部分。

### 8.1 Semantic Canonical Identity

平台內部認為某事件的主要身分：

```text
event://GEID
```

這是資料與知識身分。

### 8.2 HTTP／SEO Canonical

搜尋引擎 `rel="canonical"` 解決的是頁面重複與網址偏好。

若兩個子站對同一事件提供不同領域解釋：

$$
Projection_A(e)\neq Projection_B(e)
$$

就不應因為共享 GEID 而強迫兩頁 SEO canonical 指向同一網址。

因此：

$$
SemanticCanonical
\neq
SEOCanonical
$$

兩者應分開治理。

---

## 9. 母站不是唯一資料庫

母站在本規格中包含三種角色。

### 9.1 Control Plane

管理：

- Domain Registry；
- Site Registry；
- Pack Registry；
- Subscription Registry；
- Policy；
- Routing；
- Observability。

### 9.2 Shared Data Plane

管理：

- Event Core；
- Evidence references；
- shared entities；
- global lookup。

### 9.3 Discovery Surface

對人類提供：

- 全域搜尋；
- 跨領域探索；
- 子站導航；
- 宏觀趨勢。

這三個角色邏輯上可分離，物理上也不必部署在同一台機器。

---

## 10. 子站是自治 Projection Host

每個子站至少具有：

```text
ChildSite
├── site_id
├── domain_namespace
├── active_pack_revision
├── projection_store
├── publication_profile
├── subscription_surface
├── cache
├── local_policy_overlay
└── local_failure_domain
```

子站可以共享 Runtime，但不能失去自己的：

- taxonomy；
- relevance；
- importance；
- language；
- editorial；
- risk policy；
- publication style。

因此：

$$
SharedRuntime
\not\Rightarrow
SharedWorldview
$$

---

## 11. 建議部署模式：Shared Core + Isolated Projection

多租戶架構不存在唯一最佳隔離方式。Azure Architecture Center 目前仍將 shared-everything 與 isolated-everything 視為光譜兩端，並明確指出隔離程度與成本、擴展、管理複雜度、效能與 noisy-neighbor 風險存在取捨。

對本平台，v0.1 建議：

$$
SharedEventCore
+
NamespaceIsolatedProjection
+
OptionalDedicatedStamp
$$

即：

- 大多數站共享事件核心；
- 每站 projection 邏輯隔離；
- 高風險、高流量或特殊合規站可使用獨立 deployment stamp。

這比「所有站共用所有資料表」更安全，也比「每站完整複製全套資料」更具成本效率。

---

## 12. Tenant、Domain、Site 三者分離

不要把它們混成同一概念。

### Tenant

治理與資源邊界。

### Domain

知識語意邊界。

### Site

發布與使用者入口。

可以存在：

$$
OneTenant\rightarrow ManyDomains
$$

$$
OneDomain\rightarrow ManySites
$$

也可以：

$$
OneSite\rightarrow MultipleDomainViews
$$

因此所有主要資料表都至少應顯式區分：

```text
tenant_id
domain_namespace
site_id
```

---

## 13. Shared Event Store

Shared Event Store 的責任只有：

1. 保存全球事件身分；
2. 保存事件版本；
3. 保存 Evidence references；
4. 保存來源與事件溯源；
5. 提供跨域查詢；
6. 產生 Event Change 訊息。

它不應保存：

- 某站的 UI 排版；
- 每種語言的所有成品文字；
- 某 Domain Pack 的全部排序判斷。

其 API 可以是：

```text
GET /events/{geid}
GET /events/{geid}/versions
GET /events/{geid}/evidence
POST /events/resolve
POST /events/{geid}/merge-proposal
```

Event Merge 應屬高影響資料操作，不能由普通發布 Agent 任意執行。

---

## 14. Domain Projection Store

Projection Store 保存：

$$
Projection(d,e,t)
$$

而不是複製完整 Event。

建議資料結構：

```text
projection_id
domain_namespace
global_event_id
pack_revision
projection_version
relevance
importance
materiality
scale
taxonomy_refs
domain_delta
selection_state
language_seed
updated_at
```

Event Core 更新時，Projection 不一定立即改寫。

而是產生：

```text
event.changed
```

再由對應 Domain Worker 判定是否：

- ignore；
- refresh；
- reclassify；
- re-rank；
- human-review。

---

## 15. Publication Registry

所有公開輸出都進 Publication Registry。

```text
publication_id
projection_id
site_id
locale
channel
route
revision
content_hash
status
effect_key
published_at
supersedes
```

狀態：

```text
DRAFT
READY
PUBLISHING
PUBLISHED
FAILED
UNKNOWN
SUPERSEDED
RETRACTED
```

其中 `UNKNOWN` 很重要。

如果外部 CMS timeout：

$$
Timeout
\not\Rightarrow
PublishFailed
$$

可能頁面已建立，只是 ACK 遺失。

所以：

$$
UNKNOWN\rightarrow Reconcile
$$

而不是直接重送。

---

## 16. Publication Router

Publication Router 的輸入是：

```text
TopicSet
+
SiteRegistry
+
PublicationProfile
+
LanguageProfile
+
PolicyDecision
```

輸出：

```text
PublicationIntent[]
```

例如同一 Topic：

```text
AI Rights Event
├── agiright.org/zh-TW
├── agiright.org/en
├── agiright.org/ja
├── mother-site global feed
└── JSON feed
```

Router 只決定：

- 去哪裡；
- 用什麼 Profile；
- 需要哪種 AAL；
- 哪些 effect keys。

它不重新判斷事件重要性。

---

## 17. Publication Intent

定義：

```json
{
  "publication_intent_id": "pi_...",
  "projection_id": "dp_...",
  "site_id": "agiright",
  "locale": "zh-TW",
  "channel": "web",
  "profile_revision": "0.3.1",
  "effect_key": "publish:agiright:dp_x:zh-TW:r3",
  "required_aal": "A3"
}
```

所有外部副作用都必須先產生 Intent，再執行 Effect。

因此：

$$
Decision
\rightarrow
Intent
\rightarrow
PolicyGate
\rightarrow
Effect
\rightarrow
Ledger
$$

---

## 18. Event Bus 與 Publication Bus 分離

v0.1 建議至少分兩種事件通道。

### Event Bus

傳遞：

- event.created；
- event.updated；
- evidence.added；
- event.merged；
- event.retracted。

### Publication Bus

傳遞：

- projection.selected；
- publication.requested；
- publication.completed；
- publication.failed；
- publication.retracted。

原因是：

$$
KnowledgeChange
\neq
DeliveryEffect
$$

不能把兩者塞進同一狀態機。

---

## 19. Transport Delivery 與 Business Effect 分離

分散式訊息系統通常不能假設「每個訊息永遠只收到一次」。Google Cloud Pub/Sub 目前的 exactly-once delivery 僅支援 pull subscription，且文件仍提醒 publish-side duplicate 可能因重試而出現；Push 模式也不具同樣語意。

因此本系統的安全預設應是：

$$
Transport=AtLeastOnce
$$

而對外副作用達成：

$$
BusinessEffect\approx EffectivelyOnce
$$

方法是：

$$
IdempotencyKey
+
Inbox
+
Outbox
+
EffectLedger
+
Reconciliation
$$

---

## 20. Inbox Pattern

每個 consumer 保存：

```text
consumer_id
message_id
received_at
processed_at
result_hash
```

處理前先判定：

$$
Exists(consumer,message)
$$

若已完成：

```text
ACK_DUPLICATE
```

而不再次執行。

---

## 21. Outbox Pattern

資料庫交易內只做：

1. 更新內部狀態；
2. 寫 Outbox Record。

之後由 Relay 發送。

因此：

$$
DBCommit
\Rightarrow
MessageEventuallyPublished
$$

降低「資料改了但事件沒送出」的雙寫問題。

---

## 22. Effect Ledger

外部發布必須記錄：

```text
effect_key
effect_type
target
intent_hash
attempt
status
external_ref
started_at
completed_at
```

若：

$$
EffectKey_{new}=EffectKey_{done}
$$

則不得重做同一不可逆操作。

---

## 23. Retry Policy

所有失敗分為：

### 23.1 Retriable

- 網路 timeout；
- 429；
- 5xx；
- 暫時服務不可用。

### 23.2 Non-Retriable

- 401／403；
- Schema invalid；
- Policy denied；
- 資料缺欄位；
- 不允許的站點。

### 23.3 Unknown Effect

最危險：

- request timeout；
- 外部服務未回 ACK；
- callback 丟失。

這類必須：

$$
ReconcileBeforeRetry
$$

---

## 24. Dead-Letter Queue

當重試預算耗盡：

$$
RetryBudget=0
$$

訊息進入：

```text
DLQ
```

AWS EventBridge 現有設計同樣在 target delivery 重試耗盡後建議使用 DLQ 保存未成功事件，避免靜默遺失。

本平台 DLQ 必須保存：

- message；
- error class；
- attempts；
- first failure；
- last failure；
- site；
- domain；
- pack revision；
- replay policy。

---

## 25. Quarantine 與 DLQ 分離

DLQ 表示：

> 工作本來合法，但執行失敗。

Quarantine 表示：

> 資料或行為本身可疑，不應自動重放。

例如：

- prompt injection；
- taxonomy poisoning；
- identity conflict；
- unauthorized cross-tenant access；
- event merge ambiguity。

因此：

$$
DLQ\neq Quarantine
$$

---

## 26. Failure Domain

每個子站至少應具有獨立 failure domain。

$$
Failure(Site_A)
\not\Rightarrow
Failure(Site_B)
$$

至少隔離：

- publication queue；
- cache；
- credentials；
- rate limits；
- retry budget；
- circuit breaker。

---

## 27. Noisy Neighbor

共享 Runtime 的另一風險是某熱門站消耗全部資源。

因此每個 site/domain 設定：

```text
cpu_budget
token_budget
request_budget
queue_budget
publication_budget
concurrency_limit
```

並要求：

$$
Budget_d\le GlobalBudget
$$

單站超額時只 throttle 該站。

---

## 28. Deployment Stamp

對高流量或特殊資料領域，可以建立：

```text
Stamp A
├── Sites 1–100

Stamp B
├── Sites 101–200
```

甚至：

```text
Dedicated Stamp
└── Regulated Domain
```

這與現代多租戶架構常見的 deployment stamp／tenant isolation 光譜一致。

---

## 29. Subscription 的本質

訂閱不是：「把整站所有文章寄給我」。

而是使用者提交一個 **Interest Contract**：

$$
Sub(u)=
(Domain,Topic,Entity,Scale,Locale,Channel,Threshold,Cadence)
$$

例如：

```yaml
domain: ai-rights
topics:
  - legal-personhood
scale:
  - meso
  - macro
importance_min: 0.72
locale: zh-TW
channel: web-push
cadence: immediate
```

---

## 30. Subscription Registry

最小欄位：

```text
subscription_id
principal_id
scope
filter
locale
channel
cadence
threshold
status
lease_expiry
created_at
updated_at
```

狀態：

```text
PENDING
ACTIVE
PAUSED
EXPIRED
REVOKED
```

---

## 31. WebSub 作為公開訂閱參照

W3C WebSub 定義 publisher、hub、subscriber 三方模式：Publisher 宣告 topic 與 hub，Subscriber 向 hub 提出訂閱，Hub 負責驗證並在內容更新時分發通知；subscription 也可具有 lease duration 與 callback secret。

本平台可以採類似結構：

```text
Observatory Site = Publisher
Subscription Router = Hub
User / Agent = Subscriber
```

但內部事件訂閱不必受限於 HTTP webhook，可使用 Message Bus。

---

## 32. Subscription Filter

Filter 至少支援：

- domain；
- taxonomy node；
- entity；
- event type；
- scale；
- importance threshold；
- evidence maturity；
- language；
- geography；
- source trust；
- breaking flag。

並禁止：

- 任意 SQL；
- 任意程式執行；
- 未授權跨 tenant 查詢。

---

## 33. Interest Compilation

不要讓每個 event arrival 都重新解析完整使用者設定。

將：

$$
SubscriptionFilter
$$

編譯為：

$$
RoutingPlan
$$

例如：

```text
legal-personhood
→ subscriber set #42
```

提升大量訂閱者下的路由效率。

---

## 34. Subscription Routing

輸入：

```text
DomainProjectionChanged
```

Router 判斷：

$$
Match(Projection,Subscription)
$$

再產生：

```text
DeliveryIntent
```

而不是直接發送。

因此：

$$
Projection
\rightarrow
Match
\rightarrow
DeliveryIntent
\rightarrow
ChannelPolicy
\rightarrow
Delivery
$$

---

## 35. Cadence

支援：

```text
immediate
daily_digest
weekly_digest
threshold_only
breaking_only
```

這允許同一資訊層服務不同注意力需求。

---

## 36. 微、中、宏訂閱

承接 TH-02：

$$
Scale\in\{\mu,m,M\}
$$

使用者可以只追蹤：

- 微觀專案更新；
- 中觀領域趨勢；
- 宏觀結構改變。

因此「訂閱某領域」不再是一個二元開關。

---

## 37. Entity Subscription

除了 taxonomy，也應支援：

```text
FollowEntity(OpenAI)
FollowEntity(EU_AI_Act)
FollowEntity(Project_X)
```

但 entity subscription 不代表所有提及都通知。

仍需：

$$
Materiality\ge Threshold
$$

---

## 38. Watchlist Subscription

WP-05 的 Watchlist 可與訂閱整合。

例如使用者可選：

> 當這個尚未成熟的事件跨過證據門檻時通知我。

因此：

$$
WatchStateTransition
\rightarrow
SubscriptionTrigger
$$

---

## 39. Subscription 與 Recommendation 分離

訂閱是顯式意圖：

$$
ExplicitInterest
$$

推薦是系統推斷：

$$
InferredInterest
$$

v0.1 不混合兩者。

因此：

$$
Subscription\neq Recommendation
$$

---

## 40. Publishing 與 Subscription 分離

一個事件即使沒有公開頁面，也可能觸發內部訂閱。

反之，一個公開頁面也未必值得通知所有訂閱者。

因此：

$$
PublishDecision\neq NotifyDecision
$$

---

## 41. 多語共用 Event Identity

翻譯不建立新 Event。

$$
GEID_{zh}
=
GEID_{en}
=
GEID_{ja}
$$

差異只存在：

```text
PublicationArtifact.locale
```

若不同語言資訊本身新增不同證據，則新增 Evidence，而不是新建另一事件。

---

## 42. Language Seed 與 Rendered Text 分離

Domain Projection 可保存：

```text
language_seed
```

例如結構化事件摘要與核心術語。

不同語言再：

$$
Render(seed,locale,profile)
$$

這比每站保存五份完全獨立的事實資料更穩定。

---

## 43. Cross-Site Search

母站搜尋不應直接全文爬取所有子站頁面後再建第二套索引。

應直接索引：

$$
SharedEventCore
+
DomainProjection
+
PublicationMetadata
$$

搜尋結果可以分層呈現：

```text
Event
├── AI Rights view
├── Legal view
├── Software view
└── All evidence
```

---

## 44. 搜尋結果的身份合併

若同一 GEID 有五個 projection：

搜尋預設應先顯示一個事件群：

$$
OneEventCard
\rightarrow
ManyViews
$$

而不是五筆幾乎相同結果。

但使用者進入某子站搜尋時，可優先顯示該站 projection。

---

## 45. Event Graph Entry Point

每個事件可提供中立入口：

```text
/events/{geid}
```

其中只顯示：

- 來源；
- 時間；
- evidence；
- versions；
- 可用 domain views。

避免母站強行替事件定義唯一解釋。

---

## 46. Projection URI

領域視圖：

```text
/domains/{domain}/events/{geid}
```

或者映射到子站：

```text
https://agiright.org/topics/{slug}
```

兩者透過 `projection_id` 關聯。

---

## 47. Slug 不得成為主鍵

Slug 會因：

- 翻譯；
- 編輯；
- SEO；
- typo；
- rebranding；

而變化。

所以：

$$
Slug\neq Identity
$$

更名只更新 route mapping。

---

## 48. Route Registry

保存：

```text
route_id
site_id
publication_id
path
locale
status
redirect_from
redirect_to
```

因此 URL 改版不破壞事件身分。

---

## 49. Cache Layer

每個站可有獨立 cache，但 cache key 必須帶：

```text
site_id
domain_namespace
locale
revision
```

避免跨 tenant／跨 domain cache leakage。

Azure 多租戶 Compute 指引目前也明確提醒，共享 cache 若保留狀態，應將 tenant identifier 納入 cache key 以防資料交叉洩漏。

---

## 50. Cache Invalidation

Publication 更新後產生：

```text
publication.updated
```

Cache Worker 只失效：

$$
AffectedKeys(PUBID)
$$

而不是清空所有站。

---

## 51. Stale-While-Revalidate

公開新聞頁可以允許短時間舊快取：

$$
Availability>InstantFreshness
$$

但撤回、法律要求或重大錯誤修正可以設定：

```text
hard_invalidate = true
```

立即失效。

---

## 52. Data Ownership

v0.1 建議：

### Shared Core owns

- GEID；
- Evidence Identity；
- Source snapshot refs；
- event lineage。

### Domain owns

- taxonomy；
- relevance；
- importance；
- delta interpretation；
- selection state。

### Site owns

- URL；
- layout；
- channel；
- locale rendering；
- audience settings。

### User owns

- subscriptions；
- notification preferences。

---

## 53. Authority Matrix

不能讓任一站任意修改 Shared Event Core。

例如：

| 操作 | Child Site | Domain Agent | Core Curator | Human Gate |
|---|---:|---:|---:|---:|
| 新增 Projection | Yes | Yes | — | 視風險 |
| 修改重要性 | Yes | Yes | — | No/Conditional |
| 新增 Evidence | Proposal | Yes | Yes | 視來源 |
| Merge GEID | No | Proposal | Yes | 高門檻 |
| Retract Event Core | No | Proposal | Yes | Required |
| 改 URL | Yes | — | — | No |

---

## 54. Merge Proposal

當子站認為：

$$
GEID_a=GEID_b
$$

不得直接 merge。

先建立：

```text
EventMergeProposal
```

包含：

- evidence；
- coreference score；
- affected projections；
- affected publications；
- rollback plan。

Merge 完成後保留 alias lineage。

---

## 55. Split Proposal

反過來，如果原本一個事件後來發現其實是兩個不同事件：

$$
GEID_x\rightarrow\{GEID_a,GEID_b\}
$$

也必須保留 split lineage。

這直接銜接 WP-07 的版本鏈。

---

## 56. Projection Rebuild

當 Domain Pack 升版：

```text
0.3.1 → 0.4.0
```

可以排程：

$$
RebuildProjection(GEID,PackRevision)
$$

但：

$$
OldProjection\neq Delete
$$

舊投影應進歷史版本。

---

## 57. Publication Rebuild

投影變更後不一定要立刻改公開頁。

由 Publication Policy 判定：

```text
NO_OP
PATCH
REGENERATE
RETRACT
HUMAN_REVIEW
```

因此資料更新與公開效果解耦。

---

## 58. Eventual Consistency

母子站之間不要求所有資料在毫秒內一致。

允許：

$$
CoreVersion=v+1
$$

而某站暫時仍：

$$
ProjectionVersion(v)
$$

但必須能量測：

```text
projection_lag
publication_lag
subscription_lag
```

---

## 59. Consistency Class

可依資料類型指定：

### C0 — eventual

一般摘要、標籤。

### C1 — bounded stale

重要新聞排序。

### C2 — strong-ish coordination

Event Merge、Retract、權限修改。

不是所有資料都需要相同一致性成本。

---

## 60. Replay

事件匯流排必須支援：

$$
Replay(message\ range)
$$

但 replay 不等於重新執行外部效果。

Consumer 必須依 `message_id` 與 `effect_key` 去重。

因此：

$$
ReplaySafe
\Rightarrow
IdempotentConsumers
$$

---

## 61. Backfill

新增子站時，可從歷史 Shared Event Core：

$$
H_{core}
$$

批次建立：

$$
Projection_{newDomain}(H_{core})
$$

不用重新抓整個 Web。

這是母子站架構最重要的長期收益之一。

---

## 62. Backfill Budget

歷史回填可能非常耗算力。

因此：

```text
backfill_budget
max_events_per_run
max_tokens_per_run
max_cost
pause_threshold
```

與即時流量隔離。

---

## 63. 新子站 Onboarding

最小流程：

$$
RegisterDomain
\rightarrow
ValidatePack
\rightarrow
RegisterSite
\rightarrow
ProvisionProjectionStore
\rightarrow
DryRun
\rightarrow
BackfillSample
\rightarrow
PublishPreview
\rightarrow
Activate
$$

不要求新站複製整個平台。

---

## 64. Site Registry

欄位：

```text
site_id
tenant_id
domain_namespace
default_locale
supported_locales
active_pack_revision
publication_profile
subscription_enabled
isolation_class
deployment_stamp
status
```

狀態：

```text
PROVISIONING
STAGED
ACTIVE
PAUSED
DEGRADED
RETIRED
```

---

## 65. Domain Registry

保存：

```text
domain_namespace
parent_domain
concept_scheme
pack_registry_ref
owner
policy_profile
status
```

支援：

$$
DomainParent\rightarrow DomainChild
$$

但這只是導航結構，不代表唯一知識分類。

---

## 66. Hierarchical Subscription

使用者訂閱父領域時，可指定：

```text
include_children: true
```

例如：

```text
AI
├── AI Rights
├── AI Models
└── AI Agents
```

但預設不應無限遞迴所有後代，避免意外資訊洪水。

---

## 67. Subscription Budget

每位使用者也有注意力預算：

$$
NotificationBudget_u
$$

例如：

```text
max_immediate_per_day = 5
max_digest_items = 20
```

避免訂閱系統反過來製造新的資訊混沌。

---

## 68. Notification Deduplication

如果同一 GEID 同時符合三個訂閱：

```text
AI Rights
Legal Personhood
EU Regulation
```

預設只通知一次，並顯示：

```text
Matched 3 subscriptions
```

所以：

$$
OneGEID\rightarrow OneUserNotification
$$

除非不同 subevent 已跨過新差分門檻。

---

## 69. Notification Delta

同事件只有在：

$$
MaterialDelta(e,t_2)>\tau_u
$$

才再次通知。

不因文章數增加而重複通知。

---

## 70. Public Feed

每個子站可以提供：

- JSON Feed；
- RSS／Atom；
- WebSub；
- API；
- email digest；
- Agent subscription endpoint。

但都從同一 Projection／Publication Registry 產生。

---

## 71. Agent-to-Agent Subscription

未來 AI Agent 也可以成為 subscriber。

例如研究 Agent 訂閱：

```text
Domain: Formal Mathematics
Topic: RH
EvidenceMaturity >= E3
```

事件達標後喚醒自己的研究 Loop。

因此訂閱系統未來不只是人類通知系統，而是：

$$
KnowledgeEvent\rightarrow AgentWakeup
$$

---

## 72. Subscription Risk

不能讓訂閱直接觸發高風險操作。

例如：

```text
news event → auto buy stock
```

這應被 WP-03 Risk Policy 阻止。

所以：

$$
SubscriptionTrigger
\neq
ExternalAuthority
$$

訂閱最多形成 Intent，再走 Policy Gate。

---

## 73. Credentials Isolation

每個站的發布憑證：

```text
secret://sites/{site_id}/publisher
```

不得出現在：

- Domain Pack；
- Event payload；
- Subscription payload；
- Log 明文。

---

## 74. Cross-Tenant Authorization

所有 Data Plane 查詢都必須帶 context：

```text
principal
tenant_id
domain_namespace
site_id
purpose
```

Access Decision：

$$
Allow=f(Principal,Tenant,Resource,Action,Purpose)
$$

而不是只看 URL。

---

## 75. Row-Level Isolation

若多站共享資料庫，至少：

```text
tenant_id
namespace
```

不可缺少。

如果使用 RLS，必須確保 tenant identity 從應用層一路傳到資料層。Azure 現有多租戶資料指引也特別提醒，RLS 可以提供隔離，但身份傳遞與維護複雜度很高，因此不能把 RLS 當唯一防線。

---

## 76. Defense in Depth

推薦：

$$
Identity
+
Authorization
+
NamespaceKey
+
RLS/Partition
+
Audit
+
Tests
$$

而不是只靠其中一層。

---

## 77. Privacy Boundary

Shared Event Core 不代表所有站都能讀所有原始證據。

Evidence 可以標記：

```text
PUBLIC
LICENSED
PRIVATE
RESTRICTED
```

Projection 只拿到：

$$
AllowedEvidence(principal,domain)
$$

---

## 78. Derived Data Policy

即使原始 Evidence 不可跨站分享，某些衍生 metadata 可能可以共享。

但必須由 policy 決定：

```text
share_event_identity
share_claim_hash
share_summary
share_embedding
share_snapshot
```

不能默認所有 derived data 都無限制。

---

## 79. Provenance Across Sites

每個 Publication 必須可追溯：

$$
PUBID
\rightarrow
DPID
\rightarrow
GEID
\rightarrow
EVID
$$

同時保存：

- generator version；
- pack revision；
- model；
- human override；
- publication effect。

---

## 80. Audit Query

最小支援：

```text
Why was this page published?
Which event did it derive from?
Which evidence supported it?
Which pack revision classified it?
Which subscriptions were notified?
Which retries occurred?
Was human review involved?
```

---

## 81. Observability

至少量測：

```text
core_event_ingest_rate
projection_refresh_rate
projection_lag
publication_success_rate
publication_lag
subscription_match_rate
delivery_success_rate
duplicate_delivery_rate
effect_dedup_rate
dlq_depth
quarantine_depth
site_error_rate
cross_tenant_denial_count
```

---

## 82. Site Health

每站計算：

$$
Health_d
=f(
QueueLag,
PublishErrors,
CacheErrors,
Budget,
PolicyFailures
)
$$

站點 `DEGRADED` 時：

- 停止即時通知；
- 保留事件收集；
- 允許稍後補發。

這比整個平台一起停機更合理。

---

## 83. Circuit Breaker

若某 CMS 連續失敗：

$$
FailureRate>\tau
$$

打開 Circuit：

```text
OPEN
```

暫停該 target，避免大量 retry 壓垮系統。

---

## 84. Publication Freeze

高風險事件發生時可只凍結單站：

```text
site.publish.freeze = true
```

但：

- Event ingestion 繼續；
- Projection 可以繼續；
- History 繼續保存。

因此：

$$
PublishFreeze\neq KnowledgeFreeze
$$

---

## 85. Maintenance Mode

母站維護時，子站若具本地 projection/cache，可以維持 read-only。

所以最成熟的架構不應是：

$$
MotherDown\Rightarrow AllChildrenDown
$$

至少公開閱讀應能降級存活。

---

## 86. Control Plane Unavailable

Control Plane 短暫不可用時：

- 不接受新 Pack；
- 不修改 subscription；
- 不改 policy；
- 已授權 worker 可按 pinned config 繼續低風險工作。

即：

$$
FailStable
$$

而不是亂猜最新設定。

---

## 87. Pinned Revision

所有 Run、Projection 與 Publication Intent 必須綁定：

```text
pack_revision
policy_revision
router_revision
```

避免執行途中配置漂移。

---

## 88. Idempotent Subscription Delivery

Delivery Intent 產生：

$$
DeliveryKey
=
Hash(
SubscriptionID,
GEID,
DeltaVersion,
Channel
)
$$

同一 key 已完成就不再通知。

---

## 89. Digest Builder

每日摘要不是把 immediate notification 收集起來而已。

應重新做集合選擇：

$$
DigestSet
=Select(
MatchedDeltas,
AttentionBudget
)
$$

避免一天 50 個通知在 digest 又出現 50 個項目。

---

## 90. Parent Dashboard

母站後台至少顯示：

- active sites；
- active domains；
- event ingest；
- projection lag；
- publish failures；
- subscriber count；
- DLQ；
- quarantine；
- cost by domain；
- top cross-domain events。

但不應直接修改子站語意判斷，除非具有相應權限。

---

## 91. AGIRight v0.1 遷移

現行 AGIRight 可逐步遷移：

### M0 — 現況

```text
AGIRight Topics
→ local data
→ local render
```

### M1 — Identity Split

加入：

```text
EVID
GEID
DPID
PUBID
```

### M2 — Shared Event Core

把來源與 Event 身分搬到 Shared Core。

### M3 — Projection Store

AGIRight 只保存：

- taxonomy；
- relevance；
- importance；
- editorial。

### M4 — Publication Registry

網站頁面改由 Publication Artifact 管理。

### M5 — Subscription Router

加入：

- Topic subscription；
- entity follow；
- digest。

### M6 — Second Domain

加入與 AI Rights 明顯不同的第二個 Domain Pack，驗證：

$$
SharedCore
+
IndependentProjection
$$

是否真的成立。

---

## 92. 最小 API Contract

### Shared Event

```text
GET  /v1/events/{geid}
GET  /v1/events/{geid}/evidence
GET  /v1/events/{geid}/projections
POST /v1/events/resolve
```

### Projection

```text
GET  /v1/domains/{domain}/events/{geid}
POST /v1/domains/{domain}/project
POST /v1/domains/{domain}/rebuild
```

### Publication

```text
POST /v1/publications/intents
GET  /v1/publications/{pubid}
POST /v1/publications/{pubid}/reconcile
POST /v1/publications/{pubid}/retract
```

### Subscription

```text
POST /v1/subscriptions
GET  /v1/subscriptions/{id}
PATCH /v1/subscriptions/{id}
DELETE /v1/subscriptions/{id}
```

---

## 93. 最小 Event Types

```text
org.evemiss.iiodo.event.created.v1
org.evemiss.iiodo.event.updated.v1
org.evemiss.iiodo.evidence.added.v1
org.evemiss.iiodo.projection.updated.v1
org.evemiss.iiodo.topic.selected.v1
org.evemiss.iiodo.publication.requested.v1
org.evemiss.iiodo.publication.completed.v1
org.evemiss.iiodo.publication.failed.v1
org.evemiss.iiodo.subscription.matched.v1
org.evemiss.iiodo.delivery.completed.v1
```

Event type 必須版本化。

---

## 94. 驗收測試

### T1 — Cross-Site Identity

同一事件進入兩個 Domain：

$$
GEID_A=GEID_B
$$

但：

$$
DPID_A\neq DPID_B
$$

### T2 — Duplicate Delivery

同一訊息送達兩次，Publication 只產生一次外部效果。

### T3 — Site Failure Isolation

Site A CMS 故障，不影響 Site B 發布。

### T4 — Pack Upgrade

Pack 升級後只建立新 Projection Revision，不覆寫歷史。

### T5 — Cross-Tenant Leak

Tenant A 無法讀 Tenant B private projection。

### T6 — Subscription Dedup

同 GEID 符合三個使用者 filters，只通知一次。

### T7 — Unknown Effect

外部 timeout 後先 reconcile，不直接 duplicate publish。

### T8 — Replay

Event Bus replay 不產生重複 Publication Effect。

### T9 — Mother Control Plane Failure

控制平面暫停時，已發布子站仍可 read-only 服務。

### T10 — Event Split

一個 GEID 被 split 後，舊 publications 仍可追溯其 lineage。

---

## 95. 核心不變式

### Invariant 1

$$
OneOccurrence\rightarrow OneSharedEventIdentity
$$

在平台當前最佳判斷下成立；若之後修正，以 merge／split lineage 保留歷史。

### Invariant 2

$$
OneGEID\rightarrow ManyDPID
$$

合法。

### Invariant 3

$$
OneDPID\rightarrow ManyPUBID
$$

合法。

### Invariant 4

$$
PublicationArtifact\not\equiv SourceOfTruth
$$

### Invariant 5

$$
TransportDuplicate
\not\Rightarrow
EffectDuplicate
$$

### Invariant 6

$$
Failure(Site_i)
\not\Rightarrow
Failure(Site_j)
$$

### Invariant 7

$$
SemanticCanonical\neq SEOCanonical
$$

### Invariant 8

$$
SubscriptionTrigger\neq ExternalAuthority
$$

### Invariant 9

所有跨站共享資料都必須有清楚的 access policy 與 provenance。

### Invariant 10

$$
History\neq Overwrite
$$

所有 Projection／Publication 重大修改必須保留 lineage。

---

## 96. 與現有工程體系的關係

本規格並非從零發明事件與多租戶架構。

CloudEvents 提供跨平台事件資料的共同 envelope，尤其 `source + id` 的重複辨識、`type` 的路由／政策用途，以及 `subject`、`time`、`dataschema` 等上下文欄位，適合作為內部事件匯流排的參照。

W3C WebSub 則展示了 Publisher–Hub–Subscriber 的 Web 原生發布／訂閱模型，證明「發布者不必逐一知道所有訂閱者」本身是一個成熟架構模式。

Google Cloud Pub/Sub 的現行 exactly-once 文件提醒我們，真正的傳遞保證取決於 subscription 類型與 acknowledgment 模式，而且 publish-side duplicate 仍可能存在。這正是本規格不把可靠性建立在「消息永遠只送一次」，而建立在 Inbox、Idempotency、Effect Ledger 與 Reconciliation 上的原因。

AWS EventBridge 的 retry／DLQ 模型提供另一個成熟參照：事件傳遞失敗時可以有 retry budget，而耗盡後將事件送入 DLQ，避免靜默遺失。

Azure Architecture Center 的多租戶文件則持續強調 shared-everything 到 fully-isolated 之間存在光譜，隔離、成本、規模、管理與 noisy-neighbor 風險需要逐元件取捨，而不是整個系統只選一種 tenancy 模式。

本文件的新意不在單一 Pub/Sub、Event Bus 或 multitenancy 技術，而在於把：

$$
SharedEventIdentity
+
PluralDomainProjection
+
PublicationArtifact
+
SubscriptionContract
+
RiskAwareRuntime
+
ReplayableHistory
$$

組合成適合「大量領域觀測站」的母子網站資料與分發架構。

---

## 97. 參考資料與工程查核

本文件於 2026-08-01 重新查核以下資料：

1. Microsoft Azure Architecture Center, **Architectural approaches for a multitenant solution**：共享與隔離光譜、Deployment Stamps、成本／隔離／效能／管理取捨。
   - https://learn.microsoft.com/en-us/azure/architecture/guide/multitenant/approaches/overview
2. Microsoft Azure Architecture Center, **Architectural approaches for storage and data in multitenant solutions**：共享資料庫、tenant-level isolation、RLS 與資料隔離的工程取捨。
   - https://learn.microsoft.com/en-us/azure/architecture/guide/multitenant/approaches/storage-data
3. Microsoft Azure Architecture Center, **Architectural approaches for compute in multitenant solutions**：共享 compute、tenant isolation、noisy neighbor、cache key 加 tenant identity。
   - https://learn.microsoft.com/en-us/azure/architecture/guide/multitenant/approaches/compute
4. Microsoft Azure Architecture Center, **Tenancy models for a multitenant solution**：Tenant、Deployment、Isolation Spectrum 與 Deployment Stamp。
   - https://learn.microsoft.com/en-us/azure/architecture/guide/multitenant/considerations/tenancy-models
5. CNCF CloudEvents, **CloudEvents Specification**：事件 envelope、`id`、`source`、`type`、`subject`、`time`、`dataschema` 與重複事件識別。
   - https://github.com/cloudevents/spec/blob/main/cloudevents/spec.md
6. W3C, **WebSub Recommendation**：Publisher、Hub、Subscriber、subscription verification、lease、callback distribution。
   - https://www.w3.org/TR/websub/
7. Google Cloud, **Pub/Sub exactly-once delivery**：pull subscription 的 exactly-once 語意、acknowledgment、publish-side duplicates 與 push subscription 限制。
   - https://docs.cloud.google.com/pubsub/docs/exactly-once-delivery
8. AWS, **How EventBridge retries delivering events**：retry policy、exponential backoff、failure exhaustion 與 Dead-Letter Queue。
   - https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-rule-retry-policy.html
9. AWS, **What Amazon EventBridge logs for event buses**：event bus matching、target invocation、retry、DLQ 與 delivery observability。
   - https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-event-logs-execution-steps.html

---

## 98. 下一階段

WP-06 完成後，系統已具有：

$$
SharedEventCore
+
DomainProjection
+
PublicationRegistry
+
SubscriptionRegistry
+
EventBus
+
EffectSafeDelivery
$$

下一個問題是：

> 這些 Event、Evidence、Projection、Merge／Split、Retract 與 Publication Revision，如何跨年保存，並讓系統真正回答「當時世界是什麼狀態？」

因此下一篇 EML-IIODO-WP-07 將處理：

# 《時序事件資料庫、來源快照與版本鏈 v0.1》

正式建立：

$$
ValidTime
+
SystemTime
+
ObservationTime
+
ImmutableSnapshot
+
EventVersion
+
CorrectionChain
+
MergeSplitLineage
+
HistoricalReplay
$$

並把前四篇理論中的「當時所知」與「今日回看」真正落成資料模型。

---

## 99. 結論

當領域觀測站只有一個時，「一個網站一個資料庫」看起來非常合理。

但當資訊海開始被大量微型、中型與宏觀領域觀測站持續整理後，真正可擴張的單位不再是網站，而是：

$$
\boxed{
SharedEvent
+
DomainProjection
+
PublicationSurface
}
$$

母站的責任不是替所有子站定義唯一世界觀，而是維護：

- 共同事件身分；
- 證據與來源；
- 路由；
- 權限；
- 版本；
- 訂閱；
- 可觀測性；
- 故障隔離。

子站則保留：

- 領域分類；
- 重要性；
- 差分判斷；
- 編輯風格；
- 多語呈現；
- 專屬使用者入口。

因此最終結構不是：

$$
MotherSite
\rightarrow
ManyCopiedPages
$$

而是：

$$
\boxed{
InternetInformationOcean
\rightarrow
SharedEventCore
\rightarrow
ManyDomainProjections
\rightarrow
ManySitesAndSubscriptions
}
$$

同一片資訊海只需要辨認一次共同事件，但可以被無數不同領域重新理解。

這正是母子網站模式真正適合本系列的原因：

> **母站提供共同記憶與協調能力；子站提供局部視角與注意力入口；訂閱系統讓人類與 AI 只接收自己真正關心的那一小片變化。**

當這一層成立後，下一個難題自然不再是「怎麼發出去」，而是「如何讓幾年、幾十年後仍能準確回到當時的事件版本、來源快照與判斷狀態」。

那正是時序事件資料庫與版本鏈要處理的問題。
