feat: add scoped read-only audio preview and isolated Dify transport

This commit is contained in:
2026-10-09 16:10:59 +08:00
parent 27772bec61
commit 4d0af7f3f4
36 changed files with 1517 additions and 68 deletions
@@ -17,6 +17,7 @@ final class FollowupAudioApply
public static function apply(int $taskId, int $version, array $items, int $actor, array $info): array
{
FollowupAudioGate::assertMayApply(); // Before DB, root checks and the already-applied idempotent path.
FollowupAudioStore::assertEnabled();
// Scope helpers perform ordinary reads. READ COMMITTED avoids a pre-lock actor/scope snapshot,
// and SET TRANSACTION changes this one transaction only (never the connection/session default).
@@ -26,6 +27,7 @@ final class FollowupAudioApply
$connection->execute('SET TRANSACTION ISOLATION LEVEL READ COMMITTED');
$result = Db::transaction(static function () use ($taskId, $version, $items, $actor, $info): array {
$task = FollowupAudioStore::lockTask($taskId);
FollowupAudioGate::assertMayApply($task);
FollowupAudioStore::assertEnabled((string) $task['model_key']);
$info = FollowupAudioAccess::actor($actor);
FollowupAudioAccess::task($taskId, $actor, $info);
@@ -93,6 +95,7 @@ final class FollowupAudioApply
if ($identityValues !== []) { self::assertIdentityMutable($diagnosis, $identityValues, $actor, $info); }
$applied = [];
foreach ($selected as $item) {
FollowupAudioGate::assertMayApply($task);
$kind = $item['kind'];
$table = self::TABLES[$kind];
$targetId = $kind === 'diagnosis' ? (int) $diagnosis['id'] : (int) ($item['target_id'] ?? 0);