@einja/dev-cli 0.1.9 → 0.1.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -2
- package/dist/cli.js +3 -6
- package/dist/cli.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +11 -6
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/list.js +1 -1
- package/dist/commands/list.js.map +1 -1
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +69 -7
- package/dist/commands/sync.js.map +1 -1
- package/dist/commands/sync.test.js +11 -25
- package/dist/commands/sync.test.js.map +1 -1
- package/dist/commands/task-loop/index.d.ts.map +1 -1
- package/dist/commands/task-loop/index.js +5 -2
- package/dist/commands/task-loop/index.js.map +1 -1
- package/dist/commands/task-loop/lib/__mocks__/child-process.mock.d.ts +227 -0
- package/dist/commands/task-loop/lib/__mocks__/child-process.mock.d.ts.map +1 -0
- package/dist/commands/task-loop/lib/__mocks__/child-process.mock.js +351 -0
- package/dist/commands/task-loop/lib/__mocks__/child-process.mock.js.map +1 -0
- package/dist/commands/task-loop/lib/__mocks__/sample-issues.d.ts +46 -0
- package/dist/commands/task-loop/lib/__mocks__/sample-issues.d.ts.map +1 -0
- package/dist/commands/task-loop/lib/__mocks__/sample-issues.js +224 -0
- package/dist/commands/task-loop/lib/__mocks__/sample-issues.js.map +1 -0
- package/dist/commands/task-loop/lib/branch-manager.d.ts.map +1 -1
- package/dist/commands/task-loop/lib/branch-manager.js +14 -8
- package/dist/commands/task-loop/lib/branch-manager.js.map +1 -1
- package/dist/commands/task-loop/lib/branch-manager.test.d.ts +2 -0
- package/dist/commands/task-loop/lib/branch-manager.test.d.ts.map +1 -0
- package/dist/commands/task-loop/lib/branch-manager.test.js +539 -0
- package/dist/commands/task-loop/lib/branch-manager.test.js.map +1 -0
- package/dist/commands/task-loop/lib/conflict-handler.js +1 -1
- package/dist/commands/task-loop/lib/conflict-handler.js.map +1 -1
- package/dist/commands/task-loop/lib/dependency-resolver.test.d.ts +2 -0
- package/dist/commands/task-loop/lib/dependency-resolver.test.d.ts.map +1 -0
- package/dist/commands/task-loop/lib/dependency-resolver.test.js +1129 -0
- package/dist/commands/task-loop/lib/dependency-resolver.test.js.map +1 -0
- package/dist/commands/task-loop/lib/gh-setup.d.ts.map +1 -1
- package/dist/commands/task-loop/lib/gh-setup.js.map +1 -1
- package/dist/commands/task-loop/lib/github-client.d.ts.map +1 -1
- package/dist/commands/task-loop/lib/github-client.js +3 -3
- package/dist/commands/task-loop/lib/github-client.js.map +1 -1
- package/dist/commands/task-loop/lib/github-client.test.d.ts +2 -0
- package/dist/commands/task-loop/lib/github-client.test.d.ts.map +1 -0
- package/dist/commands/task-loop/lib/github-client.test.js +377 -0
- package/dist/commands/task-loop/lib/github-client.test.js.map +1 -0
- package/dist/commands/task-loop/lib/issue-parser.js +4 -4
- package/dist/commands/task-loop/lib/issue-parser.js.map +1 -1
- package/dist/commands/task-loop/lib/issue-parser.test.d.ts +2 -0
- package/dist/commands/task-loop/lib/issue-parser.test.d.ts.map +1 -0
- package/dist/commands/task-loop/lib/issue-parser.test.js +854 -0
- package/dist/commands/task-loop/lib/issue-parser.test.js.map +1 -0
- package/dist/commands/task-loop/lib/pull-request-manager.d.ts +35 -0
- package/dist/commands/task-loop/lib/pull-request-manager.d.ts.map +1 -0
- package/dist/commands/task-loop/lib/pull-request-manager.js +150 -0
- package/dist/commands/task-loop/lib/pull-request-manager.js.map +1 -0
- package/dist/commands/task-loop/lib/task-number-utils.d.ts +10 -4
- package/dist/commands/task-loop/lib/task-number-utils.d.ts.map +1 -1
- package/dist/commands/task-loop/lib/task-number-utils.js +19 -10
- package/dist/commands/task-loop/lib/task-number-utils.js.map +1 -1
- package/dist/commands/task-loop/lib/task-number-utils.test.d.ts +2 -0
- package/dist/commands/task-loop/lib/task-number-utils.test.d.ts.map +1 -0
- package/dist/commands/task-loop/lib/task-number-utils.test.js +379 -0
- package/dist/commands/task-loop/lib/task-number-utils.test.js.map +1 -0
- package/dist/commands/task-loop/lib/task-state-manager.d.ts.map +1 -1
- package/dist/commands/task-loop/lib/task-state-manager.js +1 -1
- package/dist/commands/task-loop/lib/task-state-manager.js.map +1 -1
- package/dist/commands/task-loop/lib/task-state-manager.test.d.ts +2 -0
- package/dist/commands/task-loop/lib/task-state-manager.test.d.ts.map +1 -0
- package/dist/commands/task-loop/lib/task-state-manager.test.js +541 -0
- package/dist/commands/task-loop/lib/task-state-manager.test.js.map +1 -0
- package/dist/lib/file-system.js +1 -1
- package/dist/lib/file-system.js.map +1 -1
- package/dist/lib/mcp-config.d.ts.map +1 -1
- package/dist/lib/mcp-config.js +8 -4
- package/dist/lib/mcp-config.js.map +1 -1
- package/dist/lib/mcp-config.test.js +2 -2
- package/dist/lib/mcp-config.test.js.map +1 -1
- package/dist/lib/merger.d.ts.map +1 -1
- package/dist/lib/merger.js.map +1 -1
- package/dist/lib/preset-update/cli-repo-detector.test.js.map +1 -1
- package/dist/lib/preset-update/file-copier.d.ts +2 -0
- package/dist/lib/preset-update/file-copier.d.ts.map +1 -1
- package/dist/lib/preset-update/file-copier.js +12 -8
- package/dist/lib/preset-update/file-copier.js.map +1 -1
- package/dist/lib/preset-update/file-copier.test.js +36 -5
- package/dist/lib/preset-update/file-copier.test.js.map +1 -1
- package/dist/lib/preset-update/preset-finder.d.ts +1 -1
- package/dist/lib/preset-update/preset-finder.d.ts.map +1 -1
- package/dist/lib/preset-update/preset-finder.js +1 -1
- package/dist/lib/preset-update/preset-finder.js.map +1 -1
- package/dist/lib/preset-update/preset-finder.test.js +11 -11
- package/dist/lib/preset-update/preset-finder.test.js.map +1 -1
- package/dist/lib/preset.js +3 -3
- package/dist/lib/preset.js.map +1 -1
- package/dist/lib/sync/backup-manager.d.ts.map +1 -1
- package/dist/lib/sync/backup-manager.js +1 -1
- package/dist/lib/sync/backup-manager.js.map +1 -1
- package/dist/lib/sync/backup-manager.test.js +2 -2
- package/dist/lib/sync/backup-manager.test.js.map +1 -1
- package/dist/lib/sync/batch-processor.d.ts.map +1 -1
- package/dist/lib/sync/batch-processor.js.map +1 -1
- package/dist/lib/sync/batch-processor.test.js.map +1 -1
- package/dist/lib/sync/category-validator.d.ts.map +1 -1
- package/dist/lib/sync/category-validator.js.map +1 -1
- package/dist/lib/sync/category-validator.test.js +2 -11
- package/dist/lib/sync/category-validator.test.js.map +1 -1
- package/dist/lib/sync/conflict-reporter.d.ts.map +1 -1
- package/dist/lib/sync/conflict-reporter.js +1 -2
- package/dist/lib/sync/conflict-reporter.js.map +1 -1
- package/dist/lib/sync/conflict-reporter.test.js +2 -7
- package/dist/lib/sync/conflict-reporter.test.js.map +1 -1
- package/dist/lib/sync/diff-engine.d.ts.map +1 -1
- package/dist/lib/sync/diff-engine.js +2 -4
- package/dist/lib/sync/diff-engine.js.map +1 -1
- package/dist/lib/sync/diff-engine.test.js.map +1 -1
- package/dist/lib/sync/file-filter.d.ts.map +1 -1
- package/dist/lib/sync/file-filter.js +26 -3
- package/dist/lib/sync/file-filter.js.map +1 -1
- package/dist/lib/sync/file-filter.test.js +26 -2
- package/dist/lib/sync/file-filter.test.js.map +1 -1
- package/dist/lib/sync/hash-cache.d.ts.map +1 -1
- package/dist/lib/sync/hash-cache.js.map +1 -1
- package/dist/lib/sync/hash-cache.test.js +2 -2
- package/dist/lib/sync/hash-cache.test.js.map +1 -1
- package/dist/lib/sync/integration.test.js +289 -2
- package/dist/lib/sync/integration.test.js.map +1 -1
- package/dist/lib/sync/marker-processor.d.ts +34 -10
- package/dist/lib/sync/marker-processor.d.ts.map +1 -1
- package/dist/lib/sync/marker-processor.js +142 -41
- package/dist/lib/sync/marker-processor.js.map +1 -1
- package/dist/lib/sync/marker-processor.test.js +134 -1
- package/dist/lib/sync/marker-processor.test.js.map +1 -1
- package/dist/lib/sync/metadata-manager.d.ts.map +1 -1
- package/dist/lib/sync/metadata-manager.js.map +1 -1
- package/dist/lib/sync/metadata-manager.test.js +4 -6
- package/dist/lib/sync/metadata-manager.test.js.map +1 -1
- package/dist/lib/sync/performance.test.js +2 -2
- package/dist/lib/sync/performance.test.js.map +1 -1
- package/dist/lib/sync/seed-synchronizer.d.ts +27 -0
- package/dist/lib/sync/seed-synchronizer.d.ts.map +1 -0
- package/dist/lib/sync/seed-synchronizer.js +72 -0
- package/dist/lib/sync/seed-synchronizer.js.map +1 -0
- package/dist/lib/sync/seed-synchronizer.test.d.ts +2 -0
- package/dist/lib/sync/seed-synchronizer.test.d.ts.map +1 -0
- package/dist/lib/sync/seed-synchronizer.test.js +147 -0
- package/dist/lib/sync/seed-synchronizer.test.js.map +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/preset-update.d.ts +1 -1
- package/dist/types/sync.d.ts +4 -2
- package/dist/types/sync.d.ts.map +1 -1
- package/dist/types/sync.js.map +1 -1
- package/package.json +1 -2
- package/presets/default/.claude/agents/einja/backend-architect.md +1131 -0
- package/presets/{minimal/.claude/agents/einja/frontend → default/.claude/agents/einja}/design-engineer.md +1 -1
- package/presets/{minimal/.claude/agents/einja/frontend → default/.claude/agents/einja}/frontend-architect.md +1 -1
- package/presets/{minimal/.claude/agents/einja/frontend → default/.claude/agents/einja}/frontend-coder.md +1 -37
- package/presets/{minimal → default}/.claude/agents/einja/task/task-committer.md +12 -6
- package/presets/{minimal → default}/.claude/agents/einja/task/task-executer.md +9 -9
- package/presets/{minimal → default}/.claude/commands/einja/frontend-implement.md +1 -1
- package/presets/{minimal → default}/.claude/commands/einja/update-docs-by-task-specs.md +6 -6
- package/presets/{minimal/.claude/skills/einja/api-development → default/.claude/skills/einja-api-development}/SKILL.md +5 -5
- package/presets/{minimal/.claude/skills/einja/backend-architecture → default/.claude/skills/einja-backend-architecture}/SKILL.md +5 -5
- package/presets/{minimal/.claude/skills/einja/coding-standards → default/.claude/skills/einja-coding-standards}/SKILL.md +6 -6
- package/presets/{minimal/.claude/skills/einja/component-design → default/.claude/skills/einja-component-design}/SKILL.md +6 -6
- package/presets/{minimal/.claude/skills/einja/frontend-development → default/.claude/skills/einja-frontend-development}/SKILL.md +5 -5
- package/presets/{minimal/.claude/skills/einja/output-format → default/.claude/skills/einja-output-format}/SKILL.md +54 -5
- package/presets/{minimal → default}/preset.yaml +1 -1
- package/presets/{minimal → default}/symlinks.json +10 -10
- package/scaffolds/cli/preset.yaml +110 -0
- package/scaffolds/example/README.md +35 -0
- package/scaffolds/example/specs/issues/issue999-example-task/design.md +879 -0
- package/scaffolds/example/specs/issues/issue999-example-task/qa-tests/README.md +150 -0
- package/scaffolds/example/specs/issues/issue999-example-task/qa-tests/phase1/1-1.md +268 -0
- package/scaffolds/example/specs/issues/issue999-example-task/qa-tests/phase1/1-2.md +179 -0
- package/scaffolds/example/specs/issues/issue999-example-task/qa-tests/phase1/1-3.md +392 -0
- package/scaffolds/example/specs/issues/issue999-example-task/qa-tests/phase1/evidence/.gitkeep +0 -0
- package/scaffolds/example/specs/issues/issue999-example-task/qa-tests/phase2/2-1.md +459 -0
- package/scaffolds/example/specs/issues/issue999-example-task/qa-tests/phase2/evidence/.gitkeep +0 -0
- package/scaffolds/example/specs/issues/issue999-example-task/qa-tests/scenarios.md +125 -0
- package/scaffolds/example/specs/issues/issue999-example-task/requirements.md +494 -0
- package/scaffolds/example/specs/issues/issue999-example-task/tasks.md +212 -0
- package/scaffolds/instructions/deployment-setup.md +458 -0
- package/scaffolds/instructions/environment-setup.md +509 -0
- package/scaffolds/instructions/local-server-environment-and-worktree.md +539 -0
- package/scaffolds/instructions/task-execute.md +649 -0
- package/scaffolds/instructions/task-vibe-kanban-loop.md +495 -0
- package/scaffolds/memory/archive/.gitkeep +0 -0
- package/scaffolds/memory/decisions.md +35 -0
- package/scaffolds/memory/patterns.md +37 -0
- package/scaffolds/steering/README.md +42 -0
- package/scaffolds/steering/acceptance-criteria-and-qa-guide.md +11 -0
- package/scaffolds/steering/architecture.md +11 -0
- package/scaffolds/steering/branch-strategy.md +11 -0
- package/scaffolds/steering/commit-rules.md +12 -1
- package/scaffolds/steering/db-schema-design.md +11 -0
- package/scaffolds/steering/development/api-development.md +15 -4
- package/scaffolds/steering/development/backend-architecture.md +11 -0
- package/scaffolds/steering/development/frontend-development.md +11 -0
- package/scaffolds/steering/development/review-guidelines.md +11 -0
- package/scaffolds/steering/development/testing-strategy.md +85 -0
- package/scaffolds/steering/development-workflow.md +11 -0
- package/scaffolds/steering/infrastructure/deployment.md +11 -0
- package/scaffolds/steering/infrastructure/environment-variables.md +11 -0
- package/scaffolds/steering/product.md +11 -0
- package/scaffolds/steering/task-management.md +11 -0
- package/scaffolds/CLAUDE.md.template +0 -386
- /package/presets/{minimal → default}/.claude/agents/einja/docs/docs-updater.md +0 -0
- /package/presets/{minimal → default}/.claude/agents/einja/git/conflict-resolver.md +0 -0
- /package/presets/{minimal → default}/.claude/agents/einja/specs/spec-design-generator.md +0 -0
- /package/presets/{minimal → default}/.claude/agents/einja/specs/spec-qa-generator.md +0 -0
- /package/presets/{minimal → default}/.claude/agents/einja/specs/spec-requirements-generator.md +0 -0
- /package/presets/{minimal → default}/.claude/agents/einja/specs/spec-tasks-generator.md +0 -0
- /package/presets/{minimal → default}/.claude/agents/einja/task/task-modification-analyzer.md +0 -0
- /package/presets/{minimal → default}/.claude/agents/einja/task/task-qa.md +0 -0
- /package/presets/{minimal → default}/.claude/agents/einja/task/task-reviewer.md +0 -0
- /package/presets/{minimal → default}/.claude/commands/einja/spec-create.md +0 -0
- /package/presets/{minimal → default}/.claude/commands/einja/start-dev.md +0 -0
- /package/presets/{minimal → default}/.claude/commands/einja/sync-cursor-commands.md +0 -0
- /package/presets/{minimal → default}/.claude/commands/einja/task-exec.md +0 -0
- /package/presets/{minimal → default}/.claude/hooks/einja/biome-format.sh +0 -0
- /package/presets/{minimal → default}/.claude/hooks/einja/design-doc-check.sh +0 -0
- /package/presets/{minimal → default}/.claude/hooks/einja/detect-secrets.sh +0 -0
- /package/presets/{minimal → default}/.claude/hooks/einja/large-file-warning.sh +0 -0
- /package/presets/{minimal → default}/.claude/hooks/einja/playwright-resize.sh +0 -0
- /package/presets/{minimal → default}/.claude/hooks/einja/typecheck.sh +0 -0
- /package/presets/{minimal → default}/.claude/hooks/einja/unset-volta-recursion.sh +0 -0
- /package/presets/{minimal → default}/.claude/hooks/einja/validate-git-commit.sh +0 -0
- /package/presets/{minimal → default}/.claude/hooks/einja/warn-index-ts.sh +0 -0
- /package/presets/{minimal → default}/.claude/hooks/einja/warn-relative-import.sh +0 -0
- /package/presets/{minimal → default}/.claude/settings.json +0 -0
- /package/presets/{minimal/.claude/skills/einja/coding-standards → default/.claude/skills/einja-coding-standards}/reference/naming-conventions.md +0 -0
- /package/presets/{minimal/.claude/skills/einja/coding-standards → default/.claude/skills/einja-coding-standards}/reference/prohibited-patterns.md +0 -0
- /package/presets/{minimal/.claude/skills/einja/coding-standards → default/.claude/skills/einja-coding-standards}/reference/typescript-rules.md +0 -0
- /package/presets/{minimal/.claude/skills/einja/component-design → default/.claude/skills/einja-component-design}/reference/directory-structure.md +0 -0
- /package/presets/{minimal/.claude/skills/einja/component-design → default/.claude/skills/einja-component-design}/reference/props-patterns.md +0 -0
- /package/presets/{minimal/.claude/skills/einja/component-design → default/.claude/skills/einja-component-design}/reference/styling-guide.md +0 -0
- /package/presets/{minimal/.claude/skills/einja/conflict-resolver → default/.claude/skills/einja-conflict-resolver}/SKILL.md +0 -0
- /package/presets/{minimal/.claude/skills/einja/general-context-loader → default/.claude/skills/einja-general-context-loader}/SKILL.md +0 -0
- /package/presets/{minimal/.claude/skills/einja/spec-context-loader → default/.claude/skills/einja-spec-context-loader}/SKILL.md +0 -0
- /package/presets/{minimal/.claude/skills/einja/task-commit → default/.claude/skills/einja-task-commit}/SKILL.md +0 -0
- /package/presets/{minimal/.claude/skills/einja/task-qa → default/.claude/skills/einja-task-qa}/SKILL.md +0 -0
- /package/presets/{minimal/.claude/skills/einja/task-qa → default/.claude/skills/einja-task-qa}/reference/failure-patterns.md +0 -0
- /package/presets/{minimal/.claude/skills/einja/task-qa → default/.claude/skills/einja-task-qa}/reference/troubleshooting.md +0 -0
- /package/presets/{minimal/.claude/skills/einja/task-qa → default/.claude/skills/einja-task-qa}/reference/usage-patterns.md +0 -0
- /package/presets/{minimal/.claude/skills/einja/task-qa → default/.claude/skills/einja-task-qa}/templates/qa-test-template.md +0 -0
- /package/{templates → scaffolds/templates}/README.md +0 -0
- /package/{templates → scaffolds/templates}/design-simple.md.template +0 -0
- /package/{templates → scaffolds/templates}/design.md.template +0 -0
- /package/{templates → scaffolds/templates}/qa-test.md.template +0 -0
- /package/{templates → scaffolds/templates}/requirements.md.template +0 -0
|
@@ -0,0 +1,494 @@
|
|
|
1
|
+
# マジックリンク認証機能 要件定義書
|
|
2
|
+
|
|
3
|
+
## 概要
|
|
4
|
+
パスワードレス認証を実現するマジックリンク機能を実装し、ユーザーのログイン体験を向上させます。メールアドレスに送信される一時的なリンクをクリックすることで、パスワード入力なしに安全な認証を可能にします。
|
|
5
|
+
|
|
6
|
+
## AS-IS(現状)
|
|
7
|
+
|
|
8
|
+
### 現在の実装状況
|
|
9
|
+
- 従来のパスワードベース認証のみ対応
|
|
10
|
+
- ユーザーは複雑なパスワードを記憶する必要がある
|
|
11
|
+
- パスワードリセット機能は別途実装されている
|
|
12
|
+
- 2要素認証は未実装
|
|
13
|
+
|
|
14
|
+
### 現状の課題
|
|
15
|
+
- パスワード忘れによるログイン失敗が頻発(月間約15%のユーザー)
|
|
16
|
+
- 弱いパスワードによるセキュリティリスク
|
|
17
|
+
- パスワード管理の煩雑さによるユーザー離脱
|
|
18
|
+
- モバイルデバイスでのパスワード入力の不便さ
|
|
19
|
+
|
|
20
|
+
## TO-BE(目標状態)
|
|
21
|
+
|
|
22
|
+
### 実現したい姿
|
|
23
|
+
- メールアドレスのみでログイン可能なシステム
|
|
24
|
+
- ワンクリックで完了する認証フロー
|
|
25
|
+
- 時限式の安全なトークンによる認証
|
|
26
|
+
- モバイルフレンドリーな認証体験
|
|
27
|
+
|
|
28
|
+
### 期待される改善
|
|
29
|
+
- ログイン成功率の向上(95%以上を目標)
|
|
30
|
+
- パスワード関連のサポート問い合わせ80%削減
|
|
31
|
+
- セキュリティの向上(トークンの有効期限管理)
|
|
32
|
+
- ユーザー体験の大幅な改善
|
|
33
|
+
|
|
34
|
+
## ビジネス価値
|
|
35
|
+
- **問題**: パスワード管理の煩雑さによるユーザー離脱とセキュリティリスク
|
|
36
|
+
- **解決策**: メールベースのワンタイム認証リンクによるパスワードレス認証
|
|
37
|
+
- **期待効果**: ユーザー満足度向上、サポートコスト削減、セキュリティ強化
|
|
38
|
+
|
|
39
|
+
## スコープ
|
|
40
|
+
### 含まれるもの
|
|
41
|
+
- マジックリンクの生成・送信機能
|
|
42
|
+
- トークン検証とセッション管理
|
|
43
|
+
- リンクの有効期限管理(15分)
|
|
44
|
+
- 再送信機能
|
|
45
|
+
- ログアウト機能の改修
|
|
46
|
+
|
|
47
|
+
### 含まれないもの
|
|
48
|
+
- SMS認証
|
|
49
|
+
- ソーシャルログイン連携
|
|
50
|
+
- 生体認証
|
|
51
|
+
- 既存パスワード認証の削除(並行運用)
|
|
52
|
+
|
|
53
|
+
## ユースケース図
|
|
54
|
+
|
|
55
|
+
```mermaid
|
|
56
|
+
graph TB
|
|
57
|
+
subgraph アクター
|
|
58
|
+
User[👤 一般ユーザー]
|
|
59
|
+
Admin[👤 管理者]
|
|
60
|
+
System[🖥️ システム]
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
subgraph 認証機能
|
|
64
|
+
UC1[🔐 マジックリンクでログイン]
|
|
65
|
+
UC2[📧 リンク再送信]
|
|
66
|
+
UC3[🔓 ログアウト]
|
|
67
|
+
UC4[🔑 セッション管理]
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
subgraph セキュリティ機能
|
|
71
|
+
UC5[🛡️ セキュリティ通知受信]
|
|
72
|
+
UC6[⚠️ セッション無効化]
|
|
73
|
+
UC7[📊 ログイン履歴確認]
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
subgraph 管理機能
|
|
77
|
+
UC8[👥 ユーザーセッション管理]
|
|
78
|
+
UC9[📈 認証ログ監視]
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
User --> UC1
|
|
82
|
+
User --> UC2
|
|
83
|
+
User --> UC3
|
|
84
|
+
User --> UC5
|
|
85
|
+
User --> UC6
|
|
86
|
+
User --> UC7
|
|
87
|
+
|
|
88
|
+
Admin --> UC8
|
|
89
|
+
Admin --> UC9
|
|
90
|
+
Admin --> UC1
|
|
91
|
+
Admin --> UC3
|
|
92
|
+
|
|
93
|
+
System --> UC4
|
|
94
|
+
System --> UC5
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## 権限マトリクス
|
|
98
|
+
|
|
99
|
+
### ロール定義
|
|
100
|
+
|
|
101
|
+
| ロール | 説明 | アクセスレベル |
|
|
102
|
+
|--------|------|--------------|
|
|
103
|
+
| 未認証ユーザー (Guest) | ログインしていない状態 | 公開ページのみ |
|
|
104
|
+
| 一般ユーザー (User) | 認証済みの一般ユーザー | 自身のデータのみ |
|
|
105
|
+
| 管理者 (Admin) | システム管理権限を持つユーザー | 全データ + 管理機能 |
|
|
106
|
+
| システム (System) | 自動処理・バックグラウンド処理 | 内部処理専用 |
|
|
107
|
+
|
|
108
|
+
### 操作可否表
|
|
109
|
+
|
|
110
|
+
| 操作 | Guest | User | Admin | System |
|
|
111
|
+
|------|:-----:|:----:|:-----:|:------:|
|
|
112
|
+
| マジックリンクリクエスト | ✅ | ✅ | ✅ | ❌ |
|
|
113
|
+
| リンク再送信 | ✅ | ✅ | ✅ | ❌ |
|
|
114
|
+
| トークン検証 | ✅ | ✅ | ✅ | ✅ |
|
|
115
|
+
| ログアウト | ❌ | ✅ | ✅ | ❌ |
|
|
116
|
+
| セッション情報取得 | ❌ | ✅(自身のみ) | ✅(全て) | ✅ |
|
|
117
|
+
| セッション無効化 | ❌ | ✅(自身のみ) | ✅(全て) | ✅ |
|
|
118
|
+
| セキュリティ通知受信 | ❌ | ✅ | ✅ | ❌ |
|
|
119
|
+
| ログイン履歴確認 | ❌ | ✅(自身のみ) | ✅(全て) | ❌ |
|
|
120
|
+
| ユーザーセッション強制終了 | ❌ | ❌ | ✅ | ✅ |
|
|
121
|
+
| 認証ログ監視 | ❌ | ❌ | ✅ | ✅ |
|
|
122
|
+
| レート制限設定変更 | ❌ | ❌ | ✅ | ❌ |
|
|
123
|
+
|
|
124
|
+
### アクセス制御ルール
|
|
125
|
+
|
|
126
|
+
1. **認証前アクセス**
|
|
127
|
+
- ログインページ、マジックリンクリクエストAPIは全員アクセス可能
|
|
128
|
+
- トークン検証APIは有効なトークンがあれば誰でも利用可能
|
|
129
|
+
|
|
130
|
+
2. **認証後アクセス**
|
|
131
|
+
- ダッシュボード、プロフィールは認証必須
|
|
132
|
+
- 自身のセッション・履歴のみ閲覧・操作可能
|
|
133
|
+
|
|
134
|
+
3. **管理者アクセス**
|
|
135
|
+
- 全ユーザーのセッション管理が可能
|
|
136
|
+
- 認証ログの閲覧・分析が可能
|
|
137
|
+
- システム設定の変更が可能
|
|
138
|
+
|
|
139
|
+
## 画面要件
|
|
140
|
+
|
|
141
|
+
### 画面一覧と目的
|
|
142
|
+
|
|
143
|
+
#### 1. ログイン画面 (Login Screen)
|
|
144
|
+
**目的**: ユーザーがメールアドレスを入力してマジックリンクをリクエストする
|
|
145
|
+
|
|
146
|
+
**主要UI要素**:
|
|
147
|
+
- メールアドレス入力フィールド
|
|
148
|
+
- 「ログインリンクを送信」ボタン
|
|
149
|
+
- バリデーションエラーメッセージ表示エリア
|
|
150
|
+
- 既存のパスワードログインへのリンク(並行運用期間中)
|
|
151
|
+
|
|
152
|
+
**表示条件**:
|
|
153
|
+
- 未認証状態のユーザーがアクセス
|
|
154
|
+
|
|
155
|
+
#### 2. メール送信確認画面 (Email Sent Screen)
|
|
156
|
+
**目的**: マジックリンクの送信完了をユーザーに通知し、次のアクションを案内する
|
|
157
|
+
|
|
158
|
+
**主要UI要素**:
|
|
159
|
+
- 送信完了メッセージ(送信先メールアドレスを含む)
|
|
160
|
+
- 「メールが届かない場合」の案内
|
|
161
|
+
- 「再送信」ボタン(1分後に有効化)
|
|
162
|
+
- 「別のメールアドレスを試す」リンク
|
|
163
|
+
|
|
164
|
+
**表示条件**:
|
|
165
|
+
- マジックリンク送信APIが正常に完了した後
|
|
166
|
+
|
|
167
|
+
#### 3. トークン検証画面 (Token Verification Screen)
|
|
168
|
+
**目的**: マジックリンクのトークンを検証し、認証処理を実行する
|
|
169
|
+
|
|
170
|
+
**主要UI要素**:
|
|
171
|
+
- 検証中インジケーター(ローディングスピナー)
|
|
172
|
+
- 検証状態メッセージ
|
|
173
|
+
|
|
174
|
+
**表示条件**:
|
|
175
|
+
- メール内のマジックリンクをクリックした時
|
|
176
|
+
|
|
177
|
+
#### 4. エラー画面 (Error Screen)
|
|
178
|
+
**目的**: 認証失敗の原因を明確に伝え、リカバリーアクションを提示する
|
|
179
|
+
|
|
180
|
+
**主要UI要素**:
|
|
181
|
+
- エラーメッセージ(エラー種別ごとに異なる)
|
|
182
|
+
- リカバリーアクションボタン
|
|
183
|
+
- 期限切れ: 「新しいリンクを送信」
|
|
184
|
+
- 使用済み: 「新しいリンクを送信」
|
|
185
|
+
- 無効なトークン: 「ログインページに戻る」
|
|
186
|
+
- レート制限: 次回リクエスト可能時刻の表示
|
|
187
|
+
|
|
188
|
+
**表示条件**:
|
|
189
|
+
- トークン検証が失敗した場合
|
|
190
|
+
- レート制限に達した場合
|
|
191
|
+
|
|
192
|
+
### 画面遷移フロー
|
|
193
|
+
|
|
194
|
+
```mermaid
|
|
195
|
+
graph TD
|
|
196
|
+
A[ログイン画面] -->|メールアドレス入力<br/>送信ボタンクリック| B{バリデーション}
|
|
197
|
+
B -->|成功| C[メール送信確認画面]
|
|
198
|
+
B -->|失敗| A
|
|
199
|
+
C -->|再送信ボタンクリック| D{レート制限チェック}
|
|
200
|
+
D -->|OK| C
|
|
201
|
+
D -->|制限超過| E[エラー画面<br/>レート制限]
|
|
202
|
+
C -->|メール内リンククリック| F[トークン検証画面]
|
|
203
|
+
F -->|検証中| G{トークン検証}
|
|
204
|
+
G -->|成功| H[ダッシュボード<br/>認証完了]
|
|
205
|
+
G -->|期限切れ| I[エラー画面<br/>期限切れ]
|
|
206
|
+
G -->|使用済み| J[エラー画面<br/>使用済み]
|
|
207
|
+
G -->|無効| K[エラー画面<br/>無効なトークン]
|
|
208
|
+
I -->|新しいリンクを送信| A
|
|
209
|
+
J -->|新しいリンクを送信| A
|
|
210
|
+
K -->|ログインページに戻る| A
|
|
211
|
+
E -->|時間経過後<br/>リトライ| A
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### UIインタラクション要件
|
|
215
|
+
|
|
216
|
+
#### フォーム入力とバリデーション
|
|
217
|
+
**要件**:
|
|
218
|
+
- メールアドレスフィールドは入力中にリアルタイムバリデーションを実行しない
|
|
219
|
+
- フォーカスアウト時またはボタンクリック時にバリデーションを実行
|
|
220
|
+
- バリデーションエラーは入力フィールドの下に赤文字で表示
|
|
221
|
+
- 入力フィールドはエラー状態の時に赤枠で表示
|
|
222
|
+
|
|
223
|
+
**バリデーションルール**:
|
|
224
|
+
- 必須チェック: 空欄の場合「メールアドレスを入力してください」
|
|
225
|
+
- 形式チェック: 不正な形式の場合「有効なメールアドレスを入力してください」
|
|
226
|
+
|
|
227
|
+
#### ボタン操作
|
|
228
|
+
**要件**:
|
|
229
|
+
- 送信ボタンはクリック後、API応答まで無効化(disabled状態)
|
|
230
|
+
- 無効化中はローディングインジケーター(スピナー)を表示
|
|
231
|
+
- 再送信ボタンは1分間のカウントダウン表示後に有効化
|
|
232
|
+
- ボタンのホバー状態、フォーカス状態、無効状態を視覚的に区別
|
|
233
|
+
|
|
234
|
+
#### ローディング状態
|
|
235
|
+
**要件**:
|
|
236
|
+
- API呼び出し中はローディングスピナーを表示
|
|
237
|
+
- ローディング中はユーザー操作を無効化
|
|
238
|
+
- 3秒以上かかる場合は進捗メッセージを表示(例: 「メールを送信しています...」)
|
|
239
|
+
|
|
240
|
+
#### エラーメッセージ表示
|
|
241
|
+
**要件**:
|
|
242
|
+
- エラーメッセージは具体的で実行可能なアクションを含む
|
|
243
|
+
- システムエラーの場合は技術的詳細を隠し、ユーザーフレンドリーなメッセージを表示
|
|
244
|
+
- エラーメッセージは自動消去せず、ユーザーが閉じるまで表示
|
|
245
|
+
|
|
246
|
+
#### 成功フィードバック
|
|
247
|
+
**要件**:
|
|
248
|
+
- メール送信成功時は明確な成功メッセージを表示
|
|
249
|
+
- 認証成功時はダッシュボードへ自動リダイレクト(3秒以内)
|
|
250
|
+
- リダイレクト前に「ログインしています...」のメッセージを表示
|
|
251
|
+
|
|
252
|
+
## ユーザーストーリー
|
|
253
|
+
|
|
254
|
+
### Story 1: マジックリンクのリクエスト
|
|
255
|
+
**As a** ユーザー
|
|
256
|
+
**I want to** メールアドレスを入力してログインリンクを受け取りたい
|
|
257
|
+
**So that** パスワードを覚える必要なくログインできる
|
|
258
|
+
|
|
259
|
+
#### 受け入れ基準
|
|
260
|
+
|
|
261
|
+
##### 機能要件
|
|
262
|
+
- [ ] Given: ログインページにアクセスした
|
|
263
|
+
When: 有効なメールアドレスを入力して送信
|
|
264
|
+
Then: 成功メッセージが表示され、メールが送信される
|
|
265
|
+
[検証レベル: Integration]
|
|
266
|
+
- [ ] Given: ログインページにアクセスした
|
|
267
|
+
When: 無効なメールアドレスを入力
|
|
268
|
+
Then: エラーメッセージが表示される
|
|
269
|
+
[検証レベル: Unit]
|
|
270
|
+
- [ ] Given: マジックリンクをリクエスト済み
|
|
271
|
+
When: 1分以内に再度リクエスト
|
|
272
|
+
Then: レート制限エラーが表示される
|
|
273
|
+
[検証レベル: Integration]
|
|
274
|
+
|
|
275
|
+
##### UIインタラクション要件
|
|
276
|
+
- [ ] Given: ログイン画面を表示
|
|
277
|
+
When: メールアドレスフィールドにフォーカス
|
|
278
|
+
Then: フィールドが視覚的にフォーカス状態を示す(枠線の色変化など)
|
|
279
|
+
[検証レベル: Browser]
|
|
280
|
+
- [ ] Given: メールアドレスフィールドに入力
|
|
281
|
+
When: 空欄のまま送信ボタンをクリック
|
|
282
|
+
Then: フィールド下に「メールアドレスを入力してください」とエラー表示され、フィールドが赤枠になる
|
|
283
|
+
[検証レベル: Browser]
|
|
284
|
+
- [ ] Given: メールアドレスフィールドに入力
|
|
285
|
+
When: 不正な形式(例: "test@")で送信ボタンをクリック
|
|
286
|
+
Then: フィールド下に「有効なメールアドレスを入力してください」とエラー表示される
|
|
287
|
+
[検証レベル: Browser]
|
|
288
|
+
- [ ] Given: 有効なメールアドレスを入力
|
|
289
|
+
When: 送信ボタンをクリック
|
|
290
|
+
Then: ボタンが無効化され、ローディングスピナーが表示される
|
|
291
|
+
[検証レベル: Browser]
|
|
292
|
+
- [ ] Given: メール送信API実行中
|
|
293
|
+
When: 3秒以上経過
|
|
294
|
+
Then: 「メールを送信しています...」のメッセージが表示される
|
|
295
|
+
[検証レベル: Browser]
|
|
296
|
+
- [ ] Given: メール送信成功
|
|
297
|
+
When: API応答受信
|
|
298
|
+
Then: メール送信確認画面に遷移し、送信先アドレスが表示される
|
|
299
|
+
[検証レベル: Browser]
|
|
300
|
+
|
|
301
|
+
#### 実装の優先順位
|
|
302
|
+
P0 (必須)
|
|
303
|
+
|
|
304
|
+
---
|
|
305
|
+
|
|
306
|
+
### Story 2: マジックリンクによる認証
|
|
307
|
+
**As a** ユーザー
|
|
308
|
+
**I want to** メール内のリンクをクリックして認証を完了したい
|
|
309
|
+
**So that** 素早く安全にログインできる
|
|
310
|
+
|
|
311
|
+
#### 受け入れ基準
|
|
312
|
+
|
|
313
|
+
##### 機能要件
|
|
314
|
+
- [ ] Given: 有効なマジックリンクを受信した
|
|
315
|
+
When: リンクをクリック
|
|
316
|
+
Then: 自動的にログインされ、ダッシュボードへリダイレクト
|
|
317
|
+
[検証レベル: Integration]
|
|
318
|
+
- [ ] Given: 期限切れのリンクを受信した
|
|
319
|
+
When: リンクをクリック
|
|
320
|
+
Then: 期限切れエラーが表示され、再送信オプションが提示される
|
|
321
|
+
[検証レベル: Integration]
|
|
322
|
+
- [ ] Given: 既に使用済みのリンクを受信した
|
|
323
|
+
When: 再度リンクをクリック
|
|
324
|
+
Then: 使用済みエラーが表示される
|
|
325
|
+
[検証レベル: Integration]
|
|
326
|
+
|
|
327
|
+
##### UIインタラクション要件
|
|
328
|
+
- [ ] Given: マジックリンクをクリック
|
|
329
|
+
When: トークン検証画面に遷移
|
|
330
|
+
Then: ローディングスピナーと「認証しています...」のメッセージが表示される
|
|
331
|
+
[検証レベル: Browser]
|
|
332
|
+
- [ ] Given: トークン検証実行中
|
|
333
|
+
When: 検証処理が進行中
|
|
334
|
+
Then: ユーザー操作(戻る、リロードなど)を防ぐ仕組みが作動する
|
|
335
|
+
[検証レベル: Browser]
|
|
336
|
+
- [ ] Given: トークン検証成功
|
|
337
|
+
When: 認証完了
|
|
338
|
+
Then: 「ログインしています...」のメッセージが表示され、3秒以内にダッシュボードへリダイレクト
|
|
339
|
+
[検証レベル: Browser]
|
|
340
|
+
- [ ] Given: トークンが期限切れ
|
|
341
|
+
When: 検証失敗
|
|
342
|
+
Then: エラー画面に遷移し、「リンクの有効期限が切れています」とメッセージ表示、「新しいリンクを送信」ボタンを表示
|
|
343
|
+
[検証レベル: Browser]
|
|
344
|
+
- [ ] Given: トークンが使用済み
|
|
345
|
+
When: 検証失敗
|
|
346
|
+
Then: エラー画面に遷移し、「このリンクは既に使用されています」とメッセージ表示、「新しいリンクを送信」ボタンを表示
|
|
347
|
+
[検証レベル: Browser]
|
|
348
|
+
- [ ] Given: トークンが無効
|
|
349
|
+
When: 検証失敗
|
|
350
|
+
Then: エラー画面に遷移し、「無効なリンクです」とメッセージ表示、「ログインページに戻る」ボタンを表示
|
|
351
|
+
[検証レベル: Browser]
|
|
352
|
+
- [ ] Given: エラー画面で「新しいリンクを送信」ボタンをクリック
|
|
353
|
+
When: ボタン押下
|
|
354
|
+
Then: ログイン画面に遷移し、前回使用したメールアドレスがプリフィルされる
|
|
355
|
+
[検証レベル: Browser]
|
|
356
|
+
|
|
357
|
+
#### 実装の優先順位
|
|
358
|
+
P0 (必須)
|
|
359
|
+
|
|
360
|
+
---
|
|
361
|
+
|
|
362
|
+
### Story 3: セキュリティ通知
|
|
363
|
+
**As a** ユーザー
|
|
364
|
+
**I want to** 新しいデバイスからのログインを通知してもらいたい
|
|
365
|
+
**So that** 不正アクセスを検知できる
|
|
366
|
+
|
|
367
|
+
#### 受け入れ基準
|
|
368
|
+
|
|
369
|
+
##### 機能要件
|
|
370
|
+
- [ ] Given: 新しいデバイスからマジックリンクでログイン
|
|
371
|
+
When: 認証が成功
|
|
372
|
+
Then: セキュリティ通知メールが送信される
|
|
373
|
+
[検証レベル: Integration]
|
|
374
|
+
- [ ] Given: セキュリティ通知を受信
|
|
375
|
+
When: 身に覚えのないログイン
|
|
376
|
+
Then: ワンクリックでセッションを無効化できる
|
|
377
|
+
[検証レベル: Integration]
|
|
378
|
+
|
|
379
|
+
##### UIインタラクション要件
|
|
380
|
+
- [ ] Given: 新規デバイスからログイン成功
|
|
381
|
+
When: ダッシュボード表示
|
|
382
|
+
Then: 「新しいデバイスからのログインを検出しました」の通知バナーが表示される
|
|
383
|
+
[検証レベル: Browser]
|
|
384
|
+
- [ ] Given: セキュリティ通知メール受信
|
|
385
|
+
When: メール内の「セッションを無効化」リンクをクリック
|
|
386
|
+
Then: 確認画面が表示され、「このセッションを無効化しますか?」のメッセージと「無効化する」「キャンセル」ボタンが表示される
|
|
387
|
+
[検証レベル: Browser]
|
|
388
|
+
- [ ] Given: セッション無効化確認画面
|
|
389
|
+
When: 「無効化する」ボタンをクリック
|
|
390
|
+
Then: セッションが無効化され、「セッションを無効化しました」の成功メッセージが表示される
|
|
391
|
+
[検証レベル: Browser]
|
|
392
|
+
- [ ] Given: セッション無効化確認画面
|
|
393
|
+
When: 「キャンセル」ボタンをクリック
|
|
394
|
+
Then: 元の画面に戻り、セッションは維持される
|
|
395
|
+
[検証レベル: Browser]
|
|
396
|
+
|
|
397
|
+
#### 実装の優先順位
|
|
398
|
+
P1 (重要)
|
|
399
|
+
|
|
400
|
+
## 詳細なビジネス要件
|
|
401
|
+
|
|
402
|
+
### 認証トークン要件
|
|
403
|
+
#### マジックリンクトークン仕様
|
|
404
|
+
**要件内容**:
|
|
405
|
+
- 暗号学的に安全な256ビットのランダムトークン
|
|
406
|
+
- Base64URLエンコード形式で43文字
|
|
407
|
+
- トークンはデータベースにハッシュ化して保存(bcrypt使用)
|
|
408
|
+
- 1ユーザーあたり同時に有効なトークンは1つまで
|
|
409
|
+
|
|
410
|
+
**OK例**:
|
|
411
|
+
- `AbC123XyZ_0987654321qWeRtYuIoP-asdfghjklZXCV` - 有効な43文字のBase64URL形式
|
|
412
|
+
- `1a2B3c4D5e6F7g8H9i0J_kLmNoPqRsTuVwXyZ-123456` - 英数字と安全な特殊文字のみ
|
|
413
|
+
|
|
414
|
+
**NG例**:
|
|
415
|
+
- `short123` - 長さ不足(43文字未満)
|
|
416
|
+
- `invalid/token+with=special*chars` - 許可されない特殊文字を含む
|
|
417
|
+
- `password123` - 推測可能な単純な文字列
|
|
418
|
+
|
|
419
|
+
### メール送信要件
|
|
420
|
+
#### マジックリンクメール仕様
|
|
421
|
+
**要件内容**:
|
|
422
|
+
- 件名: 「[サービス名] ログインリンクのお知らせ」
|
|
423
|
+
- 送信元: `noreply@example.com`
|
|
424
|
+
- HTMLとテキストの両形式で送信(マルチパート)
|
|
425
|
+
- リンクの有効期限を明記(15分)
|
|
426
|
+
- セキュリティ警告文を含める
|
|
427
|
+
|
|
428
|
+
**メール本文に含める要素**:
|
|
429
|
+
- ログインリンク(ボタンとテキストリンクの両方)
|
|
430
|
+
- 有効期限の明記
|
|
431
|
+
- 「このメールに心当たりがない場合」の説明
|
|
432
|
+
- サポート連絡先
|
|
433
|
+
|
|
434
|
+
**セキュリティ要件**:
|
|
435
|
+
- SPF、DKIM、DMARCの設定必須
|
|
436
|
+
- リンクはHTTPS必須
|
|
437
|
+
- リプレイアタック防止のため、使用済みトークンは即座に無効化
|
|
438
|
+
|
|
439
|
+
### レート制限要件
|
|
440
|
+
#### リクエスト制限仕様
|
|
441
|
+
**要件内容**:
|
|
442
|
+
- 同一IPアドレス: 1分あたり3回まで
|
|
443
|
+
- 同一メールアドレス: 1分あたり1回まで
|
|
444
|
+
- 1日あたりの最大リクエスト数: 同一メールアドレスで20回まで
|
|
445
|
+
|
|
446
|
+
**制限超過時の動作**:
|
|
447
|
+
- HTTPステータス429(Too Many Requests)を返す
|
|
448
|
+
- `Retry-After`ヘッダーで次回リクエスト可能時刻を通知
|
|
449
|
+
- エラーメッセージ: 「リクエスト回数の上限に達しました。しばらく待ってから再度お試しください。」
|
|
450
|
+
|
|
451
|
+
## 非機能要件
|
|
452
|
+
|
|
453
|
+
### パフォーマンス
|
|
454
|
+
- マジックリンク生成: 100ms以内
|
|
455
|
+
- メール送信: 3秒以内
|
|
456
|
+
- トークン検証: 50ms以内
|
|
457
|
+
|
|
458
|
+
### セキュリティ
|
|
459
|
+
- トークンは暗号学的に安全な乱数生成
|
|
460
|
+
- トークンの有効期限: 15分
|
|
461
|
+
- 使用済みトークンの即座の無効化
|
|
462
|
+
- レート制限: 1分あたり3回まで
|
|
463
|
+
|
|
464
|
+
### 可用性
|
|
465
|
+
- 99.9%以上のアップタイム
|
|
466
|
+
- メール配信成功率: 99%以上
|
|
467
|
+
|
|
468
|
+
## 技術的制約
|
|
469
|
+
- 既存の認証システムとの互換性維持
|
|
470
|
+
- 現行のセッション管理システムの活用
|
|
471
|
+
- メール送信にはSendGridを使用
|
|
472
|
+
|
|
473
|
+
## 依存関係
|
|
474
|
+
- メール送信サービス(SendGrid)
|
|
475
|
+
- Redis(トークン管理)
|
|
476
|
+
- 既存のユーザー管理システム
|
|
477
|
+
|
|
478
|
+
## リスクと対策
|
|
479
|
+
| リスク | 影響度 | 発生確率 | 対策 |
|
|
480
|
+
|--------|--------|----------|------|
|
|
481
|
+
| メール遅延 | 高 | 中 | 複数のメールプロバイダーのフォールバック設定 |
|
|
482
|
+
| トークン漏洩 | 高 | 低 | 短い有効期限とワンタイム使用制限 |
|
|
483
|
+
| フィッシング攻撃 | 中 | 中 | ドメイン検証とセキュリティヘッダーの実装 |
|
|
484
|
+
|
|
485
|
+
## 成功指標
|
|
486
|
+
- ログイン成功率: 95%以上
|
|
487
|
+
- 平均認証時間: 30秒以内
|
|
488
|
+
- パスワード関連問い合わせ: 80%削減
|
|
489
|
+
- ユーザー満足度スコア: 4.5/5.0以上
|
|
490
|
+
|
|
491
|
+
## タイムライン
|
|
492
|
+
- Phase 1: 基本的なマジックリンク機能(Story 1, 2)
|
|
493
|
+
- Phase 2: セキュリティ強化(Story 3)
|
|
494
|
+
- Phase 3: 分析とモニタリング機能
|