索引に戻る

データアクセス申請・審査キュー

表
生成可能
データアクセス申請・審査キュー

作品として見る

持ち帰る

コピーして貼るか、ファイルに保存して渡す。ネットにつながらない環境には「全部入り」を 1 つ渡せば足りる。

全部入り

data-access-request-queue-everything.md

このパネルの中身を、URL の先にあるファイルの中身まで含めて 1 つにまとめた Markdown

依頼文

1.7 KB
「データアクセス申請・審査キュー」でHTML資料を作ってください。この型は実行できるので、版面を組み直す必要はありません — 必要なのは中身です。

## この型がすること
データアクセス申請を機密区分・最小権限・業務理由・承認者・再審査日・自動終了日とともに処理する。

## 渡す必要があるもの
- 匿名依頼者コード、資産、機密区分、必要な権限、利用目的、資産責任者、審査者、状態、再審査日を記録する。

## 入力の形
- `title` — string — アクセス審査の要点
- `subtitle` — string? — 申請窓口・ポリシー版・対象期間
- `program` — string — データガバナンスプログラム
- `requests` — array (3–12) — 匿名依頼者コード、資産、区分、最小権限、理由、所有者、承認、状態、期限

入力の機械可読な検証は schema.ts が持ちます。足りない入力は推測せず質問してください。

## 向かない場合
- 役割ごとの標準権限そのものを比較・設計する場合は、権限マトリクスを使う。

## 作り方
入力を JSON にまとめ、次を実行します。

```bash
node scripts/render.mjs data-access-request-queue <入力.json> --theme ink -o out.html
```

出力は 1 ファイルで完結し、外部から何も読み込みません。

## 原本
- https://design-vault.pages.dev/designs/data-access-request-queue/source/template.tsx
- https://design-vault.pages.dev/designs/data-access-request-queue/source/schema.ts
- https://design-vault.pages.dev/designs/data-access-request-queue/source/sample-data.json
- https://design-vault.pages.dev/designs/data-access-request-queue/sample.html

ファイル

テンプレート・入力スキーマ・サンプルデータ・メタ情報。この文書はこの 4 つから生成されています。 生成された文書

template.tsx

7.5 KB

/designs/data-access-request-queue/source/template.tsx

中身を見る
import type { Props } from "./schema";

const CSS = String.raw`
.asset-data-access-request-queue{font-family:var(--font-sans);color:var(--color-primary);background:var(--color-surface);max-width:var(--container-slide);margin:auto;padding:3rem 2.5rem;line-height:1.55;font-size:var(--text-body-sm)}
.asset-data-access-request-queue *{box-sizing:border-box}.asset-data-access-request-queue header{margin-bottom:1.2rem}.asset-data-access-request-queue .eyebrow{font-family:var(--font-mono);font-size:var(--text-label);color:var(--color-tertiary);margin:0 0 .6rem}.asset-data-access-request-queue h1{font-size:var(--text-h1);line-height:1.25;max-width:28em;margin:0}.asset-data-access-request-queue .subtitle{color:var(--color-secondary);margin:.65rem 0 0}.asset-data-access-request-queue .summary{display:flex;gap:1.5rem;flex-wrap:wrap;padding:.7rem 0;border-block:1px solid var(--color-outline);margin-bottom:1rem}.asset-data-access-request-queue .summary p{margin:0;color:var(--color-secondary);font-size:var(--text-label)}.asset-data-access-request-queue .summary strong{font-family:var(--font-mono);font-size:var(--text-h3);color:var(--color-primary);margin-right:.3rem}.asset-data-access-request-queue .request{padding:.85rem 0;border-top:1px solid var(--color-outline)}.asset-data-access-request-queue .request:last-child{border-bottom:1px solid var(--color-outline)}.asset-data-access-request-queue .head{display:flex;gap:.55rem;align-items:center;flex-wrap:wrap}.asset-data-access-request-queue code{font-family:var(--font-mono);font-size:var(--text-label);color:var(--color-tertiary);overflow-wrap:anywhere}.asset-data-access-request-queue .head h2{font-size:var(--text-body-md);margin:0;flex:1}.asset-data-access-request-queue .badge{font-size:var(--text-label);border:1px solid var(--color-outline);padding:.03rem .4rem;color:var(--color-secondary)}.asset-data-access-request-queue .scope{display:flex;gap:.5rem;flex-wrap:wrap;margin-top:.35rem}.asset-data-access-request-queue .purpose{margin:.55rem 0 .2rem;font-weight:600}.asset-data-access-request-queue .justification{margin:.15rem 0;color:var(--color-secondary);overflow-wrap:anywhere}.asset-data-access-request-queue .details{display:grid;grid-template-columns:1fr 1fr;gap:.4rem 1.2rem;margin-top:.55rem;padding:.5rem .65rem;background:var(--color-surface-subtle)}.asset-data-access-request-queue .details span{display:block;font-size:var(--text-label);color:var(--color-secondary)}.asset-data-access-request-queue .details p{margin:0;overflow-wrap:anywhere}.asset-data-access-request-queue .approval{font-family:var(--font-mono);font-size:var(--text-label)}.asset-data-access-request-queue .still-svg{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}
@media(max-width:680px){.asset-data-access-request-queue{padding:1.5rem 1rem}.asset-data-access-request-queue h1{font-size:var(--text-h2)}.asset-data-access-request-queue .details{grid-template-columns:minmax(0,1fr);gap:.4rem}.asset-data-access-request-queue .summary{gap:.8rem}}
@media print{.asset-data-access-request-queue{max-width:none;padding:1rem}.asset-data-access-request-queue .request{break-inside:avoid}}
`;

const statusLabel = { submitted: "申請", "owner-review": "所有者確認", "security-review": "セキュリティ審査", approved: "承認済", provisioned: "付与済", denied: "却下", revoked: "取消済" };
const classificationLabel = { public: "公開", internal: "社内", confidential: "機密", restricted: "制限" };
const accessLabel = { read: "閲覧", "limited-write": "限定編集", admin: "管理", export: "抽出" };

function Still({ data }: { data: Props }) {
  return <svg className="still-svg" data-layout-still="true" width="1280" height="720" viewBox="0 0 1280 720" aria-hidden="true">
    <rect width="1280" height="720" fill="var(--color-surface)" />
    <text x="48" y="44" fontSize="14" fontFamily="sans-serif" fill="var(--color-secondary)">{data.program}</text>
    <text x="48" y="85" fontSize="26" fontWeight="700" fontFamily="sans-serif" fill="var(--color-on-surface)">{data.title}</text>
    <text x="48" y="120" fontSize="12" fontFamily="sans-serif" fill="var(--color-secondary)">申請者コード · データ資産 · 機密区分 · 最小権限 · 審査状態 · 終了日</text>
    {data.requests.slice(0, 8).map((request, index) => {
      const y = 166 + index * 62;
      return <g key={request.id}>
        <line x1="48" x2="1232" y1={y - 19} y2={y - 19} stroke="var(--color-outline)" />
        <text x="52" y={y + 3} fontSize="11" fontFamily="monospace" fill="var(--color-tertiary)">{request.id}</text>
        <text x="150" y={y + 3} fontSize="12" fontWeight="700" fontFamily="sans-serif" fill="var(--color-on-surface)">{request.asset}</text>
        <text x="410" y={y + 3} fontSize="11" fontFamily="sans-serif" fill="var(--color-secondary)">{classificationLabel[request.classification]} · {accessLabel[request.access]}</text>
        <text x="675" y={y + 3} fontSize="11" fontFamily="sans-serif" fill="var(--color-on-surface)">{request.requesterId} · {request.owner}</text>
        <text x="1020" y={y + 3} fontSize="11" fontFamily="sans-serif" fill="var(--color-secondary)">{statusLabel[request.status]} · {request.expiry ?? "期限未設定"}</text>
      </g>;
    })}
    <text x="48" y="704" fontSize="12" fontFamily="sans-serif" fill="var(--color-secondary)">{data.requests.length}申請 · 承認・終了日つきの最小権限付与</text>
  </svg>;
}

export default function Template(data: Props) {
  const pending = data.requests.filter((request) => ["submitted", "owner-review", "security-review"].includes(request.status)).length;
  const provisioned = data.requests.filter((request) => request.status === "provisioned").length;
  const restricted = data.requests.filter((request) => request.classification === "restricted").length;
  return <section className="asset asset-data-access-request-queue">
    <style>{CSS}</style>
    <header>
      <p className="eyebrow">{data.program} · データアクセス審査</p>
      <h1>{data.title}</h1>
      {data.subtitle && <p className="subtitle">{data.subtitle}</p>}
    </header>
    <div className="summary" aria-label="申請状況"><p><strong>{data.requests.length}</strong>申請</p><p><strong>{pending}</strong>審査中</p><p><strong>{provisioned}</strong>付与済</p><p><strong>{restricted}</strong>制限区分</p></div>
    {data.requests.map((request) => <article className="request" key={request.id}>
      <div className="head"><code>{request.id}</code><h2>{request.asset}</h2><span className="badge" data-status={request.status}>{statusLabel[request.status]}</span></div>
      <div className="scope"><span className="badge" data-classification={request.classification}>{classificationLabel[request.classification]} · {request.classification}</span><span className="badge" data-access={request.access}>権限: {accessLabel[request.access]} · {request.access}</span></div>
      <p className="purpose">{request.purpose}</p><p className="justification">{request.justification}</p>
      <div className="details">
        <div><span>依頼者コード・所属</span><p>{request.requesterId} · {request.requesterTeam}</p></div>
        <div><span>資産責任者・審査者</span><p>{request.owner} · {request.reviewer}</p></div>
        <div><span>再審査日・アクセス終了日</span><p>{request.reviewDate} · {request.expiry ?? "未設定"}</p></div>
        <div><span>承認記録</span><p className="approval">{request.approvalRef ?? "審査完了後に記録"}</p></div>
      </div>
    </article>)}
    <Still data={data} />
  </section>;
}

schema.ts

2.6 KB

/designs/data-access-request-queue/source/schema.ts

中身を見る
import { z } from "zod";

const text = z.string().trim().min(1).max(160);
const short = z.string().trim().min(1).max(48);
const date = z.string().regex(/^\d{4}-\d{2}-\d{2}$/, "日付はYYYY-MM-DD形式にすること");
const requestSchema = z.object({
  id: short.describe("アクセス依頼の一意な識別子"),
  requesterId: short.describe("氏名や連絡先を含めない依頼者コード"),
  requesterTeam: short.describe("依頼チーム"),
  asset: short.describe("要求するデータ資産またはシステム"),
  classification: z.enum(["public", "internal", "confidential", "restricted"]).describe("資産の機密区分"),
  access: z.enum(["read", "limited-write", "admin", "export"]).describe("求める最小アクセス範囲"),
  purpose: short.describe("業務上の利用目的"),
  justification: text.describe("アクセスが必要な理由と対象範囲"),
  owner: short.describe("データ資産の責任者"),
  reviewer: short.describe("アクセス判断者"),
  approvalRef: short.optional().describe("承認記録の参照"),
  reviewDate: date.describe("申請内容またはアクセスの再審査日"),
  expiry: date.optional().describe("付与アクセスの終了日"),
  status: z.enum(["submitted", "owner-review", "security-review", "approved", "provisioned", "denied", "revoked"]).describe("申請から付与・取消までの状態"),
}).strict();

export const schema = z.object({
  title: text.describe("アクセス審査の要点"),
  subtitle: text.optional().describe("申請窓口・ポリシー版・対象期間"),
  program: short.describe("対象データガバナンスプログラム"),
  requests: z.array(requestSchema).min(3).max(12).describe("最小範囲・期間限定のデータアクセス申請"),
}).strict().superRefine((data, ctx) => {
  const ids = data.requests.map(({ id }) => id);
  if (new Set(ids).size !== ids.length) {
    ctx.addIssue({ code: "custom", path: ["requests"], message: "申請IDは一意にすること" });
  }
  data.requests.forEach((request, index) => {
    if (["approved", "provisioned", "revoked"].includes(request.status) && (!request.approvalRef || !request.expiry)) {
      ctx.addIssue({ code: "custom", path: ["requests", index], message: "承認済み・付与済み申請には承認記録と終了日が必要" });
    }
    if (request.expiry && request.expiry < request.reviewDate) {
      ctx.addIssue({ code: "custom", path: ["requests", index, "expiry"], message: "アクセス終了日は再審査日以後にすること" });
    }
  });
});

export type Props = z.infer<typeof schema>;

meta.yaml

1.8 KB

/designs/data-access-request-queue/source/meta.yaml

中身を見る
id: data-access-request-queue
name:
  ja: データアクセス申請・審査キュー
  en: Data Access Request and Review Queue
purpose:
  ja: データアクセス申請を機密区分・最小権限・業務理由・承認者・再審査日・自動終了日とともに処理する。
  en: Process data access requests with classification, least privilege, purpose, approver, review date, and automatic expiry.
status: published
still: ./still.png
category: governance
catalogOrder: 865
jobs:
  - assign-governance
  - prioritize-diagnose
useCases:
  - status
  - requirements
layoutKinds:
  - table
  - stack
tags:
  - data-access-request
  - least-privilege
  - approval-workflow
  - time-bound-access
  - responsive
whenToUse:
  - ja: 申請ごとに必要最小限の権限を審査し、期限と承認記録を追跡するとき。
    en: Use to review least-privilege access per request and track its expiry and approval evidence.
avoidWhen:
  - ja: 役割ごとの標準権限そのものを比較・設計する場合は、権限マトリクスを使う。
    en: Use a permission matrix to compare and design baseline permissions by role.
requiredInputs:
  - ja: 匿名依頼者コード、資産、機密区分、必要な権限、利用目的、資産責任者、審査者、状態、再審査日を記録する。
    en: Record a pseudonymous requester code, asset, classification, requested access, purpose, owner, reviewer, state, and review date.
relatedLayouts:
  - permission-matrix
  - security-exception-register
dataSchema:
  title: string — アクセス審査の要点
  subtitle: string? — 申請窓口・ポリシー版・対象期間
  program: string — データガバナンスプログラム
  requests: array (3–12) — 匿名依頼者コード、資産、区分、最小権限、理由、所有者、承認、状態、期限
sources: []

sample-data.json

2.0 KB

/designs/data-access-request-queue/source/sample-data.json

中身を見る
{
  "title": "機密顧客データの期限付き閲覧を承認し、管理者権限の申請は差し戻す",
  "subtitle": "Data Access Governance · Q3 2026 · weekly review queue",
  "program": "Northstar Data Stewardship",
  "requests": [
    { "id": "DAR-218", "requesterId": "USR-7F21", "requesterTeam": "Risk Analytics", "asset": "customer-risk-view", "classification": "confidential", "access": "read", "purpose": "Quarterly risk review", "justification": "Read-only access for the approved 2026-Q3 portfolio analysis; no row-level export is required.", "owner": "Customer Data Steward", "reviewer": "Risk Data Approver", "approvalRef": "GOV-APR-218", "reviewDate": "2026-10-01", "expiry": "2026-12-31", "status": "provisioned" },
    { "id": "DAR-221", "requesterId": "USR-90AC", "requesterTeam": "Product Insights", "asset": "checkout-events", "classification": "internal", "access": "read", "purpose": "Funnel investigation", "justification": "Compare retry behavior for the current checkout experiment; aggregate access is sufficient.", "owner": "Commerce Data Owner", "reviewer": "Product Data Steward", "reviewDate": "2026-09-29", "status": "owner-review" },
    { "id": "DAR-226", "requesterId": "USR-4D31", "requesterTeam": "Platform Support", "asset": "identity-admin-console", "classification": "restricted", "access": "admin", "purpose": "Support investigation", "justification": "The submitted scope is broader than the stated support task and has no time-bound incident reference.", "owner": "Identity Platform Owner", "reviewer": "Security Access Board", "reviewDate": "2026-09-27", "status": "denied" },
    { "id": "DAR-229", "requesterId": "USR-25B8", "requesterTeam": "Finance Operations", "asset": "invoice-aging-mart", "classification": "confidential", "access": "export", "purpose": "Month-end close", "justification": "A controlled extract is required to reconcile open invoices; export is limited to the approved finance workspace.", "owner": "Revenue Data Owner", "reviewer": "Finance Data Approver", "reviewDate": "2026-09-30", "status": "submitted" }
  ]
}