-
Notifications
You must be signed in to change notification settings - Fork 0
Add known-risks ledger and fix Assurance Audit findings #183
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
bb0b475
Add known-risks ledger and fix Assurance Audit findings
128na 3d6d75b
Fix CI failure and address review feedback in audit changes
128na 7e92ae1
Fix Discord stacktrace leak and address remaining review feedback
128na 7e951fe
[rector] Rector fixes
actions-user 98caddc
Fix Notion sync isolation gaps, scrub threshold, and DB index
128na File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| namespace App\Actions\Extract; | ||
|
|
||
| use App\Models\RawPage; | ||
| use Carbon\CarbonImmutable; | ||
| use Psr\Log\LoggerInterface; | ||
|
|
||
| /** | ||
| * 抽出失敗時の共通処理。 | ||
| * | ||
| * 以前は失敗時に RawPage を delete() していたが、一過性のエラーでも唯一の | ||
| * スクレイプ結果が恒久消失してしまうため、削除をやめて失敗を隔離・可視化する。 | ||
| * 次回以降のリトライで成功すればフラグはクリアされ自己回復する。 | ||
| */ | ||
| final class MarkExtractFailed | ||
| { | ||
| public function __invoke(LoggerInterface $logger, RawPage $rawPage, \Throwable $throwable): void | ||
| { | ||
| $logger->error('failed', [$rawPage->url, $throwable]); | ||
| $rawPage->update(['extract_failed_at' => CarbonImmutable::now()]); | ||
| } | ||
|
|
||
| /** | ||
| * 抽出が成功したら過去の失敗フラグをクリアする(自己回復)。 | ||
| */ | ||
| public function clear(RawPage $rawPage): void | ||
| { | ||
| if ($rawPage->extract_failed_at !== null) { | ||
| $rawPage->update(['extract_failed_at' => null]); | ||
| } | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,103 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| namespace App\Actions\Logging; | ||
|
|
||
| use Illuminate\Support\Facades\Config; | ||
|
|
||
| /** | ||
| * ログ・例外レポート・Discord 送出に機密値が混入するのを防ぐための伏字化。 | ||
| * | ||
| * 例外メッセージやスタックトレース、Guzzle 例外に含まれる Authorization ヘッダ等に | ||
| * 紛れ込んだ既知の機密値(Notion シークレット、Discord Webhook URL、DB パスワード)を | ||
| * 送出直前に [REDACTED] へ置換する予防制御。 | ||
| */ | ||
| final class SecretScrubber | ||
| { | ||
| private const string MASK = '[REDACTED]'; | ||
|
|
||
| /** | ||
| * @var list<string>|null | ||
| */ | ||
| private ?array $cachedSecrets = null; | ||
|
|
||
| public function scrub(string $value): string | ||
| { | ||
| $secrets = $this->secrets(); | ||
| if ($secrets === []) { | ||
| return $value; | ||
| } | ||
|
|
||
| return str_replace($secrets, self::MASK, $value); | ||
| } | ||
|
|
||
| /** | ||
| * @param array<array-key,mixed> $context | ||
| * @return array<array-key,mixed> | ||
| */ | ||
| public function scrubArray(array $context): array | ||
| { | ||
| $secrets = $this->secrets(); | ||
| if ($secrets === []) { | ||
| return $context; | ||
| } | ||
|
|
||
| /** @var array<array-key,mixed> $scrubbed */ | ||
| $scrubbed = $this->walk($context, $secrets); | ||
|
|
||
| return $scrubbed; | ||
| } | ||
|
|
||
| /** | ||
| * @param list<string> $secrets | ||
| */ | ||
| private function walk(mixed $value, array $secrets): mixed | ||
| { | ||
| if (is_string($value)) { | ||
| return str_replace($secrets, self::MASK, $value); | ||
| } | ||
|
|
||
| if (is_array($value)) { | ||
| return array_map(fn (mixed $item): mixed => $this->walk($item, $secrets), $value); | ||
| } | ||
|
|
||
| if ($value instanceof \Throwable) { | ||
| // 例外オブジェクトはメッセージ + トレース文字列に展開してから伏字化する。 | ||
| // 注意: これにより context['exception'] は Throwable から string に変わる。 | ||
| // Sentry 等、Throwable のままであることを期待する Monolog processor/handler を | ||
| // 将来追加する場合は、本プロセッサより前段に置くこと。 | ||
| return str_replace($secrets, self::MASK, (string) $value); | ||
| } | ||
|
128na marked this conversation as resolved.
|
||
|
|
||
| return $value; | ||
| } | ||
|
|
||
| /** | ||
| * 伏字化対象の機密値一覧(短すぎる値・空値は誤爆防止のため対象から除外する)。 | ||
| * リクエスト中に変わらない値なのでインスタンス単位でキャッシュする | ||
| * (静的キャッシュにすると PHPUnit のテスト間で Config 変更が反映されなくなるため避ける)。 | ||
| * | ||
| * @return list<string> | ||
| */ | ||
| private function secrets(): array | ||
| { | ||
| if ($this->cachedSecrets !== null) { | ||
| return $this->cachedSecrets; | ||
| } | ||
|
|
||
| $candidates = [ | ||
| Config::get('services.notion.secret'), | ||
| Config::get('logging.channels.discord.url'), | ||
| Config::get('database.connections.mysql.password'), | ||
| Config::get('database.connections.portal.password'), | ||
| ]; | ||
|
|
||
| return $this->cachedSecrets = array_values(array_unique(array_filter( | ||
| $candidates, | ||
| // 未設定(null)や開発環境の "root"(4文字) 等の短い値まで伏字化すると | ||
| // chroot/uproot 等の無関係な単語まで壊してしまうため、5文字未満は対象外にする。 | ||
| fn (mixed $value): bool => is_string($value) && mb_strlen($value) >= 5, | ||
| ))); | ||
| } | ||
|
128na marked this conversation as resolved.
|
||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.