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
8 changes: 8 additions & 0 deletions contracts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@ canonical schema ที่ทุก repo ใน ecosystem ต้องใช้

คำขอที่ไม่ครบ 4 ข้อไม่ได้ถูกปฏิเสธถาวร — แต่ต้องรอให้ครบก่อน ไม่ใช่ผ่านด้วยความน่าเชื่อของผู้ขอ

### ⏳ field ที่ deprecated รอลบใน major ถัดไป

| contract | field | แทนด้วย | ลบเมื่อ |
| --- | --- | --- | --- |
| `policy/v1` | `Request.subject` | `Request.actor` | `policy/v2` ([ADR-0017](../decisions/0017-the-word-subject.md)) |

field ที่ติด `deprecated: true` **ยังใช้ได้และยัง valid** — มีอยู่เพื่อไม่ให้ consumer ที่ pin อยู่ต้องขึ้น major เพราะชื่อ · แต่ **major ถัดไปที่เกิดด้วยเหตุอื่นต้องลบมันทิ้งพร้อมกัน** ไม่ใช่ปล่อยไว้เป็นชื่อที่สองถาวร — สองชื่อสำหรับสิ่งเดียวกันคือสิ่งที่ repo นี้ห้ามไว้ทุกที่ ([`expires_at: null`](consent/v1/) · `conditions: []`)

### 🔗 Derived contracts

`approval/v1` และ `event/v1` **derive semantics มาจาก `devfactory-core`** ตาม [ADR-0006 C2](../decisions/0006-contract-versioning.md) — เราเป็นเจ้าของ *รูปร่างบน wire* เขาเป็นเจ้าของ *ความหมาย*
Expand Down
5 changes: 4 additions & 1 deletion contracts/approval/v1/approval.schema.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,10 @@ properties:

subject:
type: object
description: อนุมัติให้อะไร
description: >-
อนุมัติให้อะไร — `subject` ที่นี่คือ **สิ่งที่ถูกอนุมัติ** ไม่ใช่ผู้กระทำ
และไม่ใช่เจ้าของข้อมูล ([ADR-0017](../../../decisions/0017-the-word-subject.md))
🔒 เป็น semantics ของ devfactory-core — เปลี่ยนชื่อที่นี่ไม่ได้
required: [type, id]
properties:
type:
Expand Down
4 changes: 3 additions & 1 deletion contracts/capability/v1/declaration.schema.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ required: [subject, capabilities]
properties:
subject:
type: object
description: ใครเป็นคนประกาศ
description: >-
ใครเป็นคนประกาศ — `subject` ที่นี่คือ **สิ่งที่ declaration นี้เกี่ยวกับ**
ซึ่งตรงกับคำวินิจฉัยใน [ADR-0017](../../../decisions/0017-the-word-subject.md) · ผู้กระทำใน `policy/v1` ใช้ `actor`
required: [kind, id]
properties:
kind:
Expand Down
5 changes: 5 additions & 0 deletions contracts/consent/v1/consent.schema.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,11 @@ properties:
$ref: https://schemas.agent-platform.internal/identity/v1/identity.schema.yaml#/$defs/Id
description: >-
**เจ้าของข้อมูล** — 🔒 ไม่ใช่ actor และไม่ใช่ resource

⚠️ คำว่า `subject` ในไฟล์นี้คือ **data subject** ตามศัพท์กฎหมาย (PDPA/GDPR)
ซึ่งเป็นข้อยกเว้นที่ [ADR-0017](../../../decisions/0017-the-word-subject.md) อนุญาตไว้ · `policy/v1` ใช้ `actor` เรียกผู้กระทำ
**อย่าจับคู่ `consent/v1.subject_id` กับ `policy/v1.actor` ว่าเป็นคนเดียวกัน**
— ในเคสที่สำคัญที่สุด (หมออ่านข้อมูลผู้ป่วย) มันคนละคนเสมอ
ชื่อ field เป็น `subject_id` ไม่ใช่ชื่อของโดเมน (`patient_id`, `customer_id`)
โดยเจตนา เพราะ platform ไม่รู้จักโดเมนและไม่ควรรู้

Expand Down
3 changes: 3 additions & 0 deletions contracts/event/v1/event.schema.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ properties:
$ref: https://schemas.agent-platform.internal/identity/v1/identity.schema.yaml#/$defs/WorkspaceId
description: optional เฉพาะ event ระดับ tenant ตาม ADR-0007

# ⚠️ `subject` ที่นี่ = **หัวเรื่องของบันทึก** ไม่ใช่ผู้กระทำและไม่ใช่เจ้าของข้อมูล
# ผู้กระทำอยู่ที่ `actor` · ดูตารางศัพท์ที่ lock ไว้ ([ADR-0017](../../../decisions/0017-the-word-subject.md))
# 🔒 ชื่อคู่นี้เป็น semantics ของ devfactory-core (RFC-0008) — เปลี่ยนที่นี่ไม่ได้
subject_type:
$ref: '#/$defs/SubjectType'
subject_id:
Expand Down
22 changes: 22 additions & 0 deletions contracts/policy/v1/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,27 @@
# policy/v1

## v1.2.0 — 2026-08-21

`Request` เรียกผู้กระทำว่า `subject` ขณะที่ `consent/v1` เขียนกำกับ field ชื่อเดียวกันไว้เองว่า 🔒 *"ไม่ใช่ actor"* — [ADR-0017](../../../decisions/0017-the-word-subject.md) ไล่ทั้ง `contracts/` แล้วพบว่าคำนี้ถูกใช้ใน **5 contract 3 ความหมาย** และวินิจฉัยว่า **`subject` = สิ่งที่บันทึกนั้นเกี่ยวกับ · ผู้กระทำคือ `actor`** ซึ่งทำให้ 4 ใน 5 ถูกอยู่แล้ว และเหลือไฟล์นี้ไฟล์เดียวที่ต้องแก้

* `$defs.Actor` — นิยามรูปครั้งเดียว
* `Request.actor` — ชื่อใหม่ · `Request.subject` ติด `deprecated: true` รูปเหมือนเดิมทุกอย่าง
* `Request.required` ถอด `subject` ออก เหลือ `[context, action]` แล้วใช้ **`oneOf` บังคับให้มีอย่างใดอย่างหนึ่ง ห้ามมีทั้งคู่**

### ไม่ breaking

payload เดิมที่ส่ง `subject` **ยัง valid ทุกใบ** · การถอดออกจาก `required` เป็นการผ่อน ไม่ใช่บังคับ · `oneOf` ห้ามส่งสองชื่อพร้อมกัน แต่ `actor` เพิ่งเกิด **จึงไม่มี payload เดิมใบไหนส่งทั้งคู่ได้** ไม่มีใบไหนกลายเป็น invalid

`care-agent-platform` และ `devfactory-core` ที่ pin อยู่ **ไม่ต้องทำอะไรทันที** — ย้ายไป `actor` เมื่อสะดวก

### ⏳ ต้องลบใน `policy/v2`

`subject` มีอยู่เพื่อไม่ให้ใครต้องขึ้น major เพราะชื่อเท่านั้น · **v2 ที่เกิดด้วยเหตุอื่นต้องลบมันทิ้งพร้อมกัน** ไม่ใช่ปล่อยไว้เป็นชื่อที่สองถาวร

### ที่ไม่แตะ

`event/v1` และ `approval/v1` ใช้ `subject` ในความหมายที่ถูกตามคำวินิจฉัยอยู่แล้ว และเป็น 🔒 semantics ของ `devfactory-core` ที่เปลี่ยนที่นี่ไม่ได้ · `consent/v1.subject_id` เป็น **data subject** ตามศัพท์กฎหมาย ซึ่ง ADR-0017 อนุญาตไว้เป็นข้อยกเว้น · ทั้งสามได้หมายเหตุอ้างอิงไขว้แทนการเปลี่ยนชื่อ

## v1.1.0 — 2026-08-21

เพิ่ม **ผลการประเมินความยินยอม** ตาม [ADR-0016](../../../decisions/0016-recording-which-consent-allowed-access.md) (option C)
Expand Down
42 changes: 33 additions & 9 deletions contracts/policy/v1/policy-decision.schema.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,45 @@ $defs:
description: เหตุผลเชิงปริมาณที่ทำให้ถูกปฏิเสธหรือถูกจำกัด
enum: [none, rate_limited, budget_exceeded, quota_exhausted, out_of_window]

Actor:
description: >-
**ผู้กระทำ** — *"ใครจะทำ"* ([ADR-0017](../../../decisions/0017-the-word-subject.md))

🔒 คนละอย่างกับ `subject` ในความหมายที่ contract อื่นใช้ · ดูตารางศัพท์ที่ lock ไว้
ใน [`decisions/README.md`](../../../decisions/README.md) — โดยเฉพาะ `consent/v1.subject_id`
ที่หมายถึง **เจ้าของข้อมูล** ซึ่งเป็นคนละคนกับผู้กระทำเสมอในกรณีที่น่ากังวลที่สุด
type: object
required: [principal]
properties:
principal:
$ref: https://schemas.agent-platform.internal/identity/v1/identity.schema.yaml#/$defs/Principal
agent_id:
$ref: https://schemas.agent-platform.internal/identity/v1/identity.schema.yaml#/$defs/AgentId

Request:
type: object
required: [context, subject, action]
required: [context, action]
# ต้องมี actor หรือ subject อย่างใดอย่างหนึ่ง — ห้ามมีทั้งคู่
# ([ADR-0017](../../../decisions/0017-the-word-subject.md)) · payload เดิมที่ส่ง `subject`
# ยัง valid ทุกใบ และไม่มีใบเดิมใบไหนส่งทั้งคู่ได้เพราะ `actor` เพิ่งเกิด
oneOf:
- required: [actor]
- required: [subject]
properties:
context:
$ref: https://schemas.agent-platform.internal/identity/v1/identity.schema.yaml#/$defs/RequestContext
actor:
$ref: '#/$defs/Actor'
subject:
type: object
description: ใครจะทำ
required: [principal]
properties:
principal:
$ref: https://schemas.agent-platform.internal/identity/v1/identity.schema.yaml#/$defs/Principal
agent_id:
$ref: https://schemas.agent-platform.internal/identity/v1/identity.schema.yaml#/$defs/AgentId
$ref: '#/$defs/Actor'
deprecated: true
description: >-
⚠️ **เลิกใช้ — ใช้ `actor` แทน** · รูปเหมือนกันทุกอย่าง เปลี่ยนแค่ชื่อ

ชื่อนี้ผิดตามคำวินิจฉัยของ [ADR-0017](../../../decisions/0017-the-word-subject.md):
`subject` แปลว่า *สิ่งที่บันทึกนั้นเกี่ยวกับ* ไม่ใช่ *ผู้กระทำ* — และในไฟล์นี้มันคือผู้กระทำ

ยังอยู่เพื่อไม่ให้ consumer ที่ pin อยู่ต้องขึ้น major เพราะชื่อ · **จะถูกลบใน `policy/v2`**
action:
type: object
description: จะทำอะไร
Expand Down
Loading
Loading