索引に戻る

データ保持・廃棄台帳

表
生成可能
データ保持・廃棄台帳

作品として見る

持ち帰る

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

全部入り

data-retention-register-everything.md

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

依頼文

1.6 KB
「データ保持・廃棄台帳」でHTML資料を作ってください。この型は実行できるので、版面を組み直す必要はありません — 必要なのは中身です。

## この型がすること
保存対象ごとの起算条件・期間・処理方法・承認根拠と例外を記録する。

## 渡す必要があるもの
- 対象分類、保管先、責任者、起算条件、承認済み期間、終了後の処理、根拠を揃える。

## 入力の形
- `title` — string — 台帳の目的
- `subtitle` — string? — 対象範囲・基準日・前提
- `scope` — string — 対象システム・組織
- `records` — array (3–10) — 保存対象、起算、期間、処理、根拠、例外

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

## 向かない場合
- 法令上の保存義務や適正な期間を判断する場合は、所管の専門家と一次資料を確認する。

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

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

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

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

ファイル

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

template.tsx

8.9 KB

/designs/data-retention-register/source/template.tsx

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

const CSS = String.raw`
.asset-data-retention-register{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.6;font-size:var(--text-body-sm)}
.asset-data-retention-register *{box-sizing:border-box}.asset-data-retention-register header{margin-bottom:1.5rem}.asset-data-retention-register .eyebrow{font-family:var(--font-mono);font-size:var(--text-label);color:var(--color-tertiary);margin-bottom:.75rem}.asset-data-retention-register h1{font-size:var(--text-h1);line-height:1.3;max-width:28em}.asset-data-retention-register .subtitle{margin-top:.75rem;color:var(--color-secondary)}
.asset-data-retention-register .summary{display:flex;gap:1.5rem;flex-wrap:wrap;padding:.75rem 0;border-top:2px solid var(--color-primary);border-bottom:1px solid var(--color-outline);margin-bottom:1rem}.asset-data-retention-register .summary p{margin:0;color:var(--color-secondary);font-size:var(--text-label)}.asset-data-retention-register .summary strong{font-family:var(--font-mono);font-size:var(--text-h3);color:var(--color-primary);margin-right:.35rem}
.asset-data-retention-register .record{display:grid;grid-template-columns:minmax(9rem,1fr) minmax(0,1.25fr) minmax(7rem,.7fr) minmax(8rem,.8fr) minmax(11rem,1.1fr);gap:.9rem;padding:1rem 0;border-bottom:1px solid var(--color-outline);align-items:start;min-width:0}.asset-data-retention-register .record>*{min-width:0}.asset-data-retention-register .record-head{font-weight:650;overflow-wrap:anywhere}.asset-data-retention-register .id{font-family:var(--font-mono);font-size:var(--text-label);color:var(--color-tertiary)}.asset-data-retention-register .system,.asset-data-retention-register .owner,.asset-data-retention-register .basis{color:var(--color-secondary);font-size:var(--text-label);overflow-wrap:anywhere}.asset-data-retention-register .field-label{display:block;color:var(--color-secondary);font-size:var(--text-label);margin-bottom:.2rem}.asset-data-retention-register .event{overflow-wrap:anywhere}.asset-data-retention-register .term{font-family:var(--font-mono);font-size:var(--text-h3);font-variant-numeric:tabular-nums;white-space:nowrap}.asset-data-retention-register .disposal{font-weight:650}.asset-data-retention-register .exception{font-size:var(--text-label);border-left:2px solid var(--color-outline);padding-left:.6rem;overflow-wrap:anywhere}.asset-data-retention-register .exception-active{border-color:var(--color-tertiary)}.asset-data-retention-register .basis{margin-top:.45rem}.asset-data-retention-register footer{margin-top:1.1rem;padding-top:.75rem;border-top:1px solid var(--color-outline);color:var(--color-secondary);font-size:var(--text-label)}.asset-data-retention-register .still-svg{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}
@media(max-width:760px){.asset-data-retention-register{padding:1.5rem 1rem}.asset-data-retention-register h1{font-size:var(--text-h2)}.asset-data-retention-register .record{grid-template-columns:minmax(0,1fr) auto;gap:.6rem 1rem;padding:.9rem 0}.asset-data-retention-register .record-head{grid-column:1}.asset-data-retention-register .term{grid-column:2;grid-row:1/3;text-align:right}.asset-data-retention-register .event{grid-column:1/3}.asset-data-retention-register .disposal{grid-column:1}.asset-data-retention-register .exception{grid-column:2;grid-row:4/6}.asset-data-retention-register .basis{grid-column:1/3;margin-top:0}.asset-data-retention-register .system,.asset-data-retention-register .owner{display:inline}.asset-data-retention-register .summary{gap:1rem}}
@media(print){.asset-data-retention-register{max-width:none;padding:1rem}.asset-data-retention-register .record{break-inside:avoid}}
`;

const units = { days: "日", months: "か月", years: "年" };
const disposalNames = { delete: "削除", anonymize: "匿名化", archive: "アーカイブ" };
const compact = (value: string, max: number) => [...value].length > max ? `${[...value].slice(0, max - 1).join("")}…` : value;

function Still({ data }: { data: Props }) {
  const records = data.records.slice(0, 10);
  const rowHeight = 52;
  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="48" fontSize="14" fontFamily="sans-serif" fill="var(--color-secondary)">{data.scope}</text>
    <text x="48" y="87" fontSize="28" fontWeight="700" fontFamily="sans-serif" fill="var(--color-on-surface)">{compact(data.title, 54)}</text>
    <text x="48" y="116" fontSize="13" fontFamily="sans-serif" fill="var(--color-secondary)">起算条件 → 保存期間 → 処理方法 · 期間値は組織方針から転記</text>
    <text x="48" y="148" fontSize="12" fontFamily="sans-serif" fill="var(--color-secondary)">保存対象 / 保管先</text>
    <text x="430" y="148" fontSize="12" fontFamily="sans-serif" fill="var(--color-secondary)">期間の起算</text>
    <text x="720" y="148" fontSize="12" fontFamily="sans-serif" fill="var(--color-secondary)">保存期間</text>
    <text x="870" y="148" fontSize="12" fontFamily="sans-serif" fill="var(--color-secondary)">期間終了後</text>
    <text x="1030" y="148" fontSize="12" fontFamily="sans-serif" fill="var(--color-secondary)">保留・例外 / 根拠</text>
    {records.map((record, index) => {
      const y = 180 + index * rowHeight;
      return <g key={record.id}>
        <line x1="48" x2="1232" y1={y - 17} y2={y - 17} stroke="var(--color-outline)" />
        <text x="50" y={y + 4} fontSize="11" fontFamily="sans-serif" fill="var(--color-tertiary)">{record.id}</text>
        <text x="155" y={y + 4} fontSize="12" fontWeight="600" fontFamily="sans-serif" fill="var(--color-on-surface)">{compact(record.recordClass, 21)}</text>
        <text x="155" y={y + 20} fontSize="10" fontFamily="sans-serif" fill="var(--color-secondary)">{compact(record.system, 21)}</text>
        <text x="430" y={y + 4} fontSize="11" fontFamily="sans-serif" fill="var(--color-on-surface)">{compact(record.startEvent, 31)}</text>
        <text x="720" y={y + 5} fontSize="17" fontFamily="sans-serif" fill="var(--color-on-surface)">{record.retentionValue}{units[record.retentionUnit]}</text>
        <text x="870" y={y + 4} fontSize="12" fontFamily="sans-serif" fill="var(--color-on-surface)">{disposalNames[record.disposal]}</text>
        <text x="1030" y={y + 4} fontSize="11" fontFamily="sans-serif" fill={record.exceptionStatus === "active" ? "var(--color-tertiary)" : "var(--color-secondary)"}>{record.exceptionStatus === "active" ? compact(record.exceptionReference ?? "保留あり", 18) : "保留なし"}</text>
        <text x="1030" y={y + 20} fontSize="10" fontFamily="sans-serif" fill="var(--color-secondary)">{compact(record.retentionBasis, 18)}</text>
      </g>;
    })}
    <text x="48" y="704" fontSize="12" fontFamily="sans-serif" fill="var(--color-secondary)">{data.records.length}分類 · 起算条件と期間の根拠を確認</text>
  </svg>;
}

export default function Template(data: Props) {
  const exceptions = data.records.filter((record) => record.exceptionStatus === "active").length;
  return <section className="asset asset-data-retention-register">
    <style>{CSS}</style>
    <header>
      <p className="eyebrow">{data.scope} · 保存と廃棄の方針</p>
      <h1>{data.title}</h1>
      {data.subtitle && <p className="subtitle">{data.subtitle}</p>}
    </header>
    <div className="summary" aria-label="保存対象の集計">
      <p><strong>{data.records.length}</strong>保存対象</p>
      <p><strong>{exceptions}</strong>保留・例外あり</p>
      <p>期間は各組織の承認済み方針に従う</p>
    </div>
    <div>
      {data.records.map((record) => <article className="record" key={record.id}>
        <div>
          <span className="id">{record.id}</span>
          <div className="record-head">{record.recordClass}</div>
          <div className="system">{record.system}</div>
          <div className="owner">責任者: {record.owner}</div>
        </div>
        <div className="event"><span className="field-label">起算となる出来事</span>{record.startEvent}</div>
        <div><span className="field-label">保存期間</span><div className="term">{record.retentionValue} {units[record.retentionUnit]}</div></div>
        <div><span className="field-label">期間終了後</span><div className="disposal">{disposalNames[record.disposal]}</div><p className="basis">根拠: {record.retentionBasis}</p></div>
        <div className={`exception ${record.exceptionStatus === "active" ? "exception-active" : ""}`}>
          <span className="field-label">保留・例外</span>
          {record.exceptionStatus === "active" ? `あり · ${record.exceptionReference}` : "なし"}
        </div>
      </article>)}
    </div>
    <footer>期間・起算・例外条件は、組織の承認済み方針と担当者に照らして確認する。</footer>
    <Still data={data} />
  </section>;
}

schema.ts

2.0 KB

/designs/data-retention-register/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);

export const retentionRecordSchema = z.object({
  id: short.describe("保存対象の一意な識別子"),
  recordClass: short.describe("記録・データの分類"),
  system: short.describe("保管するシステムまたは場所"),
  owner: short.describe("管理責任者またはチーム"),
  startEvent: text.describe("保存期間の起算となる出来事"),
  retentionValue: z.number().int().positive().max(9999).describe("組織方針で定めた保存期間の値"),
  retentionUnit: z.enum(["days", "months", "years"]).describe("保存期間の単位"),
  disposal: z.enum(["delete", "anonymize", "archive"]).describe("期間終了後の処理"),
  retentionBasis: text.describe("期間を定めた組織方針・記録"),
  exceptionStatus: z.enum(["none", "active"]).describe("個別の保留・例外の有無"),
  exceptionReference: text.optional().describe("保留・例外の記録IDと見直し条件"),
}).strict();

export const schema = z.object({
  title: text.describe("台帳の目的を伝える見出し"),
  subtitle: text.optional().describe("対象範囲・基準日・方針の前提"),
  scope: short.describe("対象システム・組織・リリース"),
  records: z.array(retentionRecordSchema).min(3).max(10).describe("保存対象ごとの起算・期間・処理・根拠"),
}).strict().superRefine((data, ctx) => {
  const ids = data.records.map((record) => record.id);
  if (new Set(ids).size !== ids.length) {
    ctx.addIssue({ code: "custom", path: ["records"], message: "保存対象のIDは一意にすること" });
  }
  data.records.forEach((record, index) => {
    if (record.exceptionStatus === "active" && !record.exceptionReference) {
      ctx.addIssue({ code: "custom", path: ["records", index, "exceptionReference"], message: "保留・例外には記録IDと見直し条件が必要" });
    }
  });
});

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

meta.yaml

1.6 KB

/designs/data-retention-register/source/meta.yaml

中身を見る
id: data-retention-register
name:
  ja: データ保持・廃棄台帳
  en: Data Retention and Disposal Register
purpose:
  ja: 保存対象ごとの起算条件・期間・処理方法・承認根拠と例外を記録する。
  en: Record the retention trigger, duration, disposition, approved basis, and exceptions for each data class.
status: published
still: ./still.png
category: governance
catalogOrder: 810
jobs:
  - assign-governance
useCases:
  - requirements
layoutKinds:
  - table
tags:
  - data-governance
  - retention
  - operations
  - offline
  - responsive
whenToUse:
  - ja: 承認済みの組織方針を保存対象ごとに台帳化し、起算・期間・廃棄方法・例外を確認するとき。
    en: Use to track an organization's approved retention triggers, periods, disposition, and exceptions by data class.
avoidWhen:
  - ja: 法令上の保存義務や適正な期間を判断する場合は、所管の専門家と一次資料を確認する。
    en: Do not use this register to determine legal obligations or prescribe retention periods.
requiredInputs:
  - ja: 対象分類、保管先、責任者、起算条件、承認済み期間、終了後の処理、根拠を揃える。
    en: Provide the data class, repository, owner, start event, approved duration, disposition, and policy basis.
relatedLayouts:
  - data-lineage-stages
  - permission-matrix
dataSchema:
  title: string — 台帳の目的
  subtitle: string? — 対象範囲・基準日・前提
  scope: string — 対象システム・組織
  records: array (3–10) — 保存対象、起算、期間、処理、根拠、例外
sources: []

sample-data.json

1.9 KB

/designs/data-retention-register/source/sample-data.json

中身を見る
{
  "title": "保存の起点と終了後の処理を対象ごとに揃える",
  "subtitle": "架空の業務支援クラウド|社内承認済み保持方針の抜粋",
  "scope": "業務支援クラウド",
  "records": [
    {
      "id": "DATA-01",
      "recordClass": "顧客プロフィール",
      "system": "顧客データベース",
      "owner": "顧客運用チーム",
      "startEvent": "顧客アカウントの閉鎖日",
      "retentionValue": 24,
      "retentionUnit": "months",
      "disposal": "delete",
      "retentionBasis": "架空の社内記録保持基準 R-12",
      "exceptionStatus": "none"
    },
    {
      "id": "DATA-02",
      "recordClass": "問い合わせ履歴",
      "system": "サポート管理システム",
      "owner": "サポート責任者",
      "startEvent": "問い合わせの解決日",
      "retentionValue": 18,
      "retentionUnit": "months",
      "disposal": "anonymize",
      "retentionBasis": "架空のサポート運用方針 CS-4",
      "exceptionStatus": "active",
      "exceptionReference": "保留記録 HOLD-204。担当者が四半期ごとに継続要否を確認"
    },
    {
      "id": "DATA-03",
      "recordClass": "監査イベント",
      "system": "監査ログ保管庫",
      "owner": "セキュリティ運用",
      "startEvent": "イベントの記録日",
      "retentionValue": 3,
      "retentionUnit": "years",
      "disposal": "archive",
      "retentionBasis": "架空の監査ログ方針 SEC-7",
      "exceptionStatus": "none"
    },
    {
      "id": "DATA-04",
      "recordClass": "一時アップロード",
      "system": "添付ファイル領域",
      "owner": "基盤チーム",
      "startEvent": "処理ジョブの完了日",
      "retentionValue": 30,
      "retentionUnit": "days",
      "disposal": "delete",
      "retentionBasis": "架空の一時領域運用基準 OPS-3",
      "exceptionStatus": "none"
    }
  ]
}