SCALE — Build Lab
開発パターン · TYPESCRIPT LIBRARY

セキュリティデータ管理

CATEGORY開発パターン TYPETypeScript Library EFFORT90〜240分 DIFFICULTY
PRIMARY CODE
ts · lib/security-data.ts
// Security / Admin extensions data layer

export interface AuditLog {
  id: string;
  userId: string;
  userName: string;
  action: string;
  target: string;
  system: string;
  ip: string;
  timestamp: string;
  severity: 'info' | 'warn' | 'critical';
}

export interface Secret {
  id: string;
  name: string;
  type: 'api_key' | 'password' | 'cert' | 'token';
  system: string;
  lastRotated: string;
  nextRotation: string;
  strength: number; // 0-100
}

export interface BackupRun {
  id: string;
  target: string;
  startedAt: string;
  durationMs: number;
  sizeBytes: number;
  status: 'success' | 'failed';
  retentionDays: number;
}

export interface Integration {
  id: string;
  name: string;
  category: string;
  status: 'connected' | 'error' | 'disconnected';
  lastSync: string;
  apiCallsMonth: number;
  errorCount: number;
}

const KEY_AU = 'scale-sec-audit';
const KEY_SE = 'scale-sec-secrets';
const KEY_BK = 'scale-sec-backups';
const KEY_IN = 'scale-sec-integrations';

export function loadAudit(): AuditLog[] {
  if (typeof window === 'undefined') return [];
  try { const v = localStorage.getItem(KEY_AU); return v ? JSON.parse(v) : []; } catch { return []; }
}
export function saveAudit(d: AuditLog[]) {
  if (typeof window === 'undefined') return;
  localStorage.setItem(KEY_AU, JSON.stringify(d));
}
export function loadSecrets(): Secret[] {
  if (typeof window === 'undefined') return [];
  try { const v = localStorage.getItem(KEY_SE); return v ? JSON.parse(v) : []; } catch { return []; }
}
export function saveSecrets(d: Secret[]) {
  if (typeof window === 'undefined') return;
  localStorage.setItem(KEY_SE, JSON.stringify(d));
}
export function loadBackups(): BackupRun[] {
  if (typeof window === 'undefined') return [];
  try { const v = localStorage.getItem(KEY_BK); return v ? JSON.parse(v) : []; } catch { return []; }
}
export function saveBackups(d: BackupRun[]) {
  if (typeof window === 'undefined') return;
  localStorage.setItem(KEY_BK, JSON.stringify(d));
}
export function loadIntegrations(): Integration[] {
  if (typeof window === 'undefined') return [];
  try { const v = localStorage.getItem(KEY_IN); return v ? JSON.parse(v) : []; } catch { return []; }
}
export function saveIntegrations(d: Integration[]) {
  if (typeof window === 'undefined') return;
  localStorage.setItem(KEY_IN, JSON.stringify(d));
}

export function genId(p: string): string {
  return p + '-' + Date.now() + '-' + Math.random().toString(36).slice(2, 8);
}

export function fmtBytes(n: number): string {
  if (n >= 1e9) return (n / 1e9).toFixed(2) + ' GB';
  if (n >= 1e6) return (n / 1e6).toFixed(2) + ' MB';
  if (n >= 1e3) return (n / 1e3).toFixed(2) + ' KB';
  return n + ' B';
}

export function seedIfEmpty() {
  // ダミーデータは削除済み(本番運用開始)
  return;
}

前提条件
Tailwind CSS v4TypeScript 5
USE CASES
  • ISMS対応
  • セキュリティ管理
  • 監査ログ

セキュリティデータ管理

:LiTarget: 用途

セキュリティイベント・監査ログ・脆弱性情報の管理パターン。

:LiSparkle: 特徴

  • 監査ログ
  • セキュリティイベント
  • アラート管理
  • コンプライアンス対応

:LiCode: 実コード(SCALE Base より自動抽出)

:LiInfo: lib/security-data.ts の中身そのもの。コピペ即可。

// Security / Admin extensions data layer

export interface AuditLog {
  id: string;
  userId: string;
  userName: string;
  action: string;
  target: string;
  system: string;
  ip: string;
  timestamp: string;
  severity: 'info' | 'warn' | 'critical';
}

export interface Secret {
  id: string;
  name: string;
  type: 'api_key' | 'password' | 'cert' | 'token';
  system: string;
  lastRotated: string;
  nextRotation: string;
  strength: number; // 0-100
}

export interface BackupRun {
  id: string;
  target: string;
  startedAt: string;
  durationMs: number;
  sizeBytes: number;
  status: 'success' | 'failed';
  retentionDays: number;
}

export interface Integration {
  id: string;
  name: string;
  category: string;
  status: 'connected' | 'error' | 'disconnected';
  lastSync: string;
  apiCallsMonth: number;
  errorCount: number;
}

const KEY_AU = 'scale-sec-audit';
const KEY_SE = 'scale-sec-secrets';
const KEY_BK = 'scale-sec-backups';
const KEY_IN = 'scale-sec-integrations';

export function loadAudit(): AuditLog[] {
  if (typeof window === 'undefined') return [];
  try { const v = localStorage.getItem(KEY_AU); return v ? JSON.parse(v) : []; } catch { return []; }
}
export function saveAudit(d: AuditLog[]) {
  if (typeof window === 'undefined') return;
  localStorage.setItem(KEY_AU, JSON.stringify(d));
}
export function loadSecrets(): Secret[] {
  if (typeof window === 'undefined') return [];
  try { const v = localStorage.getItem(KEY_SE); return v ? JSON.parse(v) : []; } catch { return []; }
}
export function saveSecrets(d: Secret[]) {
  if (typeof window === 'undefined') return;
  localStorage.setItem(KEY_SE, JSON.stringify(d));
}
export function loadBackups(): BackupRun[] {
  if (typeof window === 'undefined') return [];
  try { const v = localStorage.getItem(KEY_BK); return v ? JSON.parse(v) : []; } catch { return []; }
}
export function saveBackups(d: BackupRun[]) {
  if (typeof window === 'undefined') return;
  localStorage.setItem(KEY_BK, JSON.stringify(d));
}
export function loadIntegrations(): Integration[] {
  if (typeof window === 'undefined') return [];
  try { const v = localStorage.getItem(KEY_IN); return v ? JSON.parse(v) : []; } catch { return []; }
}
export function saveIntegrations(d: Integration[]) {
  if (typeof window === 'undefined') return;
  localStorage.setItem(KEY_IN, JSON.stringify(d));
}

export function genId(p: string): string {
  return p + '-' + Date.now() + '-' + Math.random().toString(36).slice(2, 8);
}

export function fmtBytes(n: number): string {
  if (n >= 1e9) return (n / 1e9).toFixed(2) + ' GB';
  if (n >= 1e6) return (n / 1e6).toFixed(2) + ' MB';
  if (n >= 1e3) return (n / 1e3).toFixed(2) + ' KB';
  return n + ' B';
}

export function seedIfEmpty() {
  // ダミーデータは削除済み(本番運用開始)
  return;
}

:LiFolder: ソースファイルのパス

/Users/oogushiyuuki/Library/CloudStorage/GoogleDrive-y-ogushi@scale-group.co.jp/マイドライブ/AI/scale-base/lib/security-data.ts

:LiHandPointer: 使い方

対象プロジェクトに該当ファイルをコピーして、props を流し込むだけ。

:LiAlertCircle: 注意事項

  • 依存パッケージを忘れず追加