{
  "schema_version": "1.0",
  "baseline": "A-document-access-service-v1",
  "phase": "Batch 8 · local/dev auth",
  "updated_at": "2026-04-20",
  "owner": "session_a",
  "purpose_en": "Access resolution contract. Describes how the backend decides visibility of a group or document under a resolved profile, and what payload the shell receives.",
  "purpose_th": "สัญญา access resolution · backend ตัดสิน visibility ตาม profile · shell รับ payload ไปแสดงผล",
  "resolution_algorithm": [
    "1. Load profile from session token (fall back to anonymous on missing/unknown)",
    "2. Compute group_id from doc_id via document_visibility_matrix.json",
    "3. If group_id in profile.hidden_groups → 'hidden-group'",
    "4. If group_id not in profile.visible_groups → 'hidden-group'",
    "5. If doc_id in profile.hidden_documents → 'not-granted'",
    "6. If profile.visible_documents is non-null list and doc_id not in it → 'hidden-doc'",
    "7. If doc_id in profile.restricted_documents → 'restricted'",
    "8. Otherwise → 'visible'"
  ],
  "precedence": "hidden_groups > hidden_documents > restricted_documents > visible_documents > visible_groups",
  "endpoints": [
    {
      "method": "GET",
      "path": "/api/access/resolve",
      "query": { "doc_id": "string (required)", "token": "string (optional · else cookie)" },
      "returns": {
        "doc_id": "string",
        "group_id": "string | null",
        "state": "visible | restricted | hidden-doc | hidden-group | not-granted",
        "allow_read": "bool",
        "allow_share": "bool",
        "allow_export": "bool",
        "banner_en": "string | null",
        "banner_th": "string | null",
        "profile_id": "string",
        "email": "string",
        "mode": "local-dev",
        "resolved_at": "ISO-8601"
      }
    },
    {
      "method": "GET",
      "path": "/api/access/groups",
      "returns": {
        "groups": [
          { "id": "string", "label_en": "string", "label_th": "string", "visible": "bool", "document_count_visible": "int" }
        ],
        "mode": "local-dev"
      }
    },
    {
      "method": "GET",
      "path": "/api/access/documents",
      "query": { "group_id": "string (optional · filter)" },
      "returns": {
        "documents": [
          { "doc_id": "string", "group_id": "string", "state": "visible|restricted|hidden-doc|hidden-group|not-granted", "allow_read": "bool" }
        ],
        "mode": "local-dev",
        "filtered_count": "int",
        "hidden_count": "int",
        "restricted_count": "int"
      }
    }
  ],
  "share_export_policy": {
    "visible":      { "allow_read": true,  "allow_share": true,  "allow_export": true,  "rationale": "No restriction" },
    "restricted":   { "allow_read": true,  "allow_share": false, "allow_export": false, "rationale": "Summary metadata shown only · full content + share + export blocked" },
    "hidden-doc":   { "allow_read": false, "allow_share": false, "allow_export": false, "rationale": "Document not included in profile" },
    "hidden-group": { "allow_read": false, "allow_share": false, "allow_export": false, "rationale": "Group not visible to profile" },
    "not-granted":  { "allow_read": false, "allow_share": false, "allow_export": false, "rationale": "Explicit deny on the document id" }
  },
  "honest_limits": [
    "Backend returns an honest flag but the shell is NOT the final enforcement layer for share/export on the public web — once a user has the URL they can share it externally. These flags drive the UI surface only.",
    "Server does not stream restricted content · shell must respect banners.",
    "Visibility decisions are computed per request · no caching in this batch.",
    "Decisions are not audited or logged beyond stdout."
  ],
  "cross_references": {
    "session_contract": "docs/runtime/document-access-service/session_contract.json",
    "user_store":       "docs/runtime/document-access-service/user_store_examples.json",
    "decision_examples":"docs/runtime/document-access-service/access_decision_examples.json",
    "visibility_matrix":"docs/assets/access/document_visibility_matrix.json",
    "access_schema":    "docs/assets/access/document_access_schema.json"
  }
}
