2026-04-24 18:21:28 +09:00

8.1 KiB
Raw Blame History

API Spec

本文件定義 File Access Agent 對外 API 邊界,以及它依賴的 Member Center File Access 授權契約。

目前狀態:

  • File Access Agent API本文件定義為本專案目標契約。
  • Member Center File Access API../member_center/docs/openapi.yaml 與相關文件整理,作為本專案整合依據。

0. 部署與資料假設

  • Single-tenant instance一個 File Access Agent instance 只服務一個 tenant。
  • 服務啟動時需設定固定 INSTANCE_TENANT_ID;所有請求中的 tenant_idtoken 或 validation 結果)都必須與此值一致。
  • 預設無 DB服務維持 stateless。
  • Metadata 讀取以 bucket provider 為主,不以本地 DB 作為權威來源。
  • 若未來出現審計、replay 防護或特殊索引需求,可再加可選持久化層。

1. 角色分工

File Access Agent

負責:

  • 驗證 upload 用的 Member Center JWT access token
  • 接收檔案上傳、下載、metadata 查詢、刪除
  • 對 delegated download token 向 Member Center 做線上驗證
  • 控制實際 bucket / file space 存取

不負責:

  • OAuth client 管理
  • access token 簽發
  • delegated download token 簽發
  • 商業規則判斷與版本管理
  • 結構化查詢或 metadata 主資料治理

Member Center

負責:

  • 簽發 upload 用的 S2S JWT access token
  • 簽發 delegated short-lived opaque download token
  • 提供 delegated token validation endpoint

2. 授權模型

2.1 Upload

  • token 來源Member Center client_credentials
  • audiencefile_access_api
  • 必要 scopefiles:upload.write
  • 必要 claimtenant_id
  • 驗證方式File Access Agent 以 Member Center JWKS 驗簽 JWT

2.2 Download

  • token 來源:業務服務以 files:download.delegate 呼叫 Member Center 申請
  • token 類型delegated short-lived opaque token
  • token 需綁定:
    • tenant_id
    • user_id
    • file_idobject_key
    • method=GET
    • 短效 exp
  • 驗證方式File Access Agent 呼叫 Member Center validation endpoint 線上驗證

2.3 Metadata

建議沿用 upload 類型的 S2S JWT

  • audiencefile_access_api
  • 必要 scopefiles:metadata.read
  • 必要 claimtenant_id

2.4 Delete

建議沿用 upload 類型的 S2S JWT

  • audiencefile_access_api
  • 必要 scopefiles:delete
  • 必要 claimtenant_id

3. File Access Agent API

Base path 暫定:/

3.1 Upload File

  • Method: PUT
  • Path: /files/{objectKey}
  • Auth: Bearer JWT
  • Required scope: files:upload.write

用途:

  • 由業務服務上傳檔案到 File Access Agent

Path parameters

  • objectKeyURL-encoded object key

Headers

  • Authorization: Bearer <access_token>
  • Content-Type: <mime-type>

Optional headers

  • X-File-Id: <string>

Request body

  • binary stream

Validation

  • JWT signature / iss / aud=file_access_api / exp
  • token tenant_id
  • scope=files:upload.write
  • request objectKey 是否符合允許的 tenant 邊界策略

Object key 命名建議(介接規範):

  • Agent 不做複雜命名治理,objectKey 由介接服務自行決定。
  • 建議 key 結構:{domain}/{entity}/{yyyy}/{MM}/{dd}/{id-or-uuid}/{sanitized-filename}
  • 建議至少包含一個高唯一性段(例如 uuid 或資料庫主鍵),避免只用原始檔名。
  • 建議避免使用空白、反斜線與 ..;上傳前先做檔名 sanitize保留副檔名
  • 建議全部使用小寫與固定分隔字元(/-),便於跨服務對齊。

避免重複檔名與版本策略(責任邊界):

  • 若上傳相同 objectKeyAgent 視為覆蓋overwrite不自動做版本保留。
  • Agent 不負責「同名檔案改名」或「自動遞增版本號」。
  • 若要避免覆蓋,介接服務應在上傳前自行產生新 key例如 timestamp + uuid)。
  • 若要做版本管理,請由介接服務把每個版本寫成不同 objectKey(例如 .../v0001/....../v0002/...)。
  • 若要保留「原始檔名查詢」能力,請在介接服務自己的資料表維護 display_name -> objectKey 對照。

Responses

  • 201 Created
  • 400 Bad Request
  • 401 Unauthorized
  • 403 Forbidden
  • 409 Conflict
  • 413 Payload Too Large

Success body

{
  "tenant_id": "uuid",
  "file_id": "optional-string",
  "object_key": "reports/2026/04/file.pdf",
  "content_type": "application/pdf",
  "size": 12345,
  "etag": "optional-string",
  "last_modified_at": "2026-04-24T03:10:00Z"
}

3.2 Download File

  • Method: GET
  • Path: /files/{objectKey}
  • Auth: delegated download token

用途:

  • 由 client 使用 delegated token 下載檔案

Path parameters

  • objectKeyURL-encoded object key

Headers

  • Authorization: Bearer <delegated_download_token>

Validation

  • 將 token 與實際 tenant_id + file_id/object_key + method=GET 邊界送到 Member Center validation endpoint
  • validation 成功後才允許下載

Responses

  • 200 OK with file stream
  • 401 Unauthorized
  • 403 Forbidden
  • 404 Not Found

3.3 Get File Metadata

  • Method: GET
  • Path: /files/metadata/{objectKey}
  • Auth: Bearer JWT
  • Required scope: files:metadata.read

用途:

  • 由業務服務讀取檔案 metadata不回傳檔案內容

Responses

  • 200 OK
  • 401 Unauthorized
  • 403 Forbidden
  • 404 Not Found

Success body

{
  "tenant_id": "uuid",
  "file_id": "optional-string",
  "object_key": "reports/2026/04/file.pdf",
  "content_type": "application/pdf",
  "size": 12345,
  "etag": "optional-string",
  "last_modified_at": "2026-04-24T03:10:00Z"
}

3.4 Head File

  • Method: HEAD
  • Path: /files/{objectKey}
  • Auth: Bearer JWT
  • Required scope: files:metadata.read

用途:

  • 提供較輕量的 existence / metadata header 檢查

Responses

  • 200 OK
  • 401 Unauthorized
  • 403 Forbidden
  • 404 Not Found

3.5 Delete File

  • Method: DELETE
  • Path: /files/{objectKey}
  • Auth: Bearer JWT
  • Required scope: files:delete

用途:

  • 由業務服務刪除檔案

Responses

  • 204 No Content
  • 401 Unauthorized
  • 403 Forbidden
  • 404 Not Found

3.6 Health

  • Method: GET
  • Path: /health
  • Auth: none

用途:

  • liveness / readiness 的最小檢查

Responses

  • 200 OK

Success body

{
  "status": "ok"
}

4. 與 Member Center 的整合 API

以下端點不屬於本專案提供,但 File Access Agent 需要依賴。

4.1 Issue Delegated Download Token

  • Provider: Member Center
  • Method: POST
  • Path: /file-access/download-tokens
  • Required scope: files:download.delegate

Request body

{
  "tenant_id": "uuid",
  "user_id": "uuid",
  "file_id": "optional-string",
  "object_key": "reports/2026/04/file.pdf",
  "method": "GET",
  "expires_in_seconds": 300
}

Response body

  • 由 Member Center 定義;目前至少會回傳 delegated download token 與到期資訊

4.2 Validate Delegated Download Token

  • Provider: Member Center
  • Method: POST
  • Path: /file-access/download-tokens/validate
  • Required scope: files:download.read

Request body

{
  "token": "opaque-token",
  "tenant_id": "uuid",
  "file_id": "optional-string",
  "object_key": "reports/2026/04/file.pdf",
  "method": "GET"
}

Response body

  • 由 Member Center 定義;目前至少需包含 validation success / active 狀態與對應邊界資訊

5. 共通錯誤格式

建議本專案統一採用:

{
  "error": "string_code",
  "message": "human readable message",
  "request_id": "uuid"
}

建議錯誤碼:

  • invalid_token
  • insufficient_scope
  • tenant_mismatch
  • object_key_mismatch
  • method_mismatch
  • file_not_found
  • payload_too_large
  • unsupported_media_type
  • storage_unavailable

6. 待補細節

  • tenant_id 從 request path、header 或 object key prefix 如何對齊
  • file_id 是否作為正式主 key或僅保留 object_key
  • HEAD /files/{objectKey} 是否保留,或改以 GET /files/metadata/{objectKey}
  • upload 是否需要支援 overwrite 策略 header
  • 下載是否要支援 Range request
  • metadata / delete 是否允許 delegated token或只接受 S2S JWT
  • 可選持久化是否需要最小 audit / jti 表(預設不啟用)