diff --git a/api/app/Http/Controllers/Api/V1/Portal/EngagementPortalController.php b/api/app/Http/Controllers/Api/V1/Portal/EngagementPortalController.php
index 2ce4471a..d8d9683a 100644
--- a/api/app/Http/Controllers/Api/V1/Portal/EngagementPortalController.php
+++ b/api/app/Http/Controllers/Api/V1/Portal/EngagementPortalController.php
@@ -257,16 +257,13 @@ final class EngagementPortalController extends Controller
// Pass event_id via the context bag โ the schema is org-owned (not
// event-owned) and this route has no {event} parameter for the
// FormSubmissionObserver fallback. ARCH-FORM-BUILDER ยง17.3 footnote.
- // idempotency_key column is varchar(30); a SHA-1 hex digest fits in
- // 28 chars and uniquely keys "one draft per (schema, engagement)".
- $key = 'aa-'.substr(hash('sha1', (string) $resolved->engagement->id), 0, 27);
-
+ // idempotency_key column is varchar(30); 'aa:' + 26-char ULID fits.
return $this->submissionService->createDraft(
schema: $schema,
subject: $resolved->subject,
submitter: null,
context: [
- 'idempotency_key' => $key,
+ 'idempotency_key' => 'aa:'.$resolved->engagement->id,
'event_id' => $resolved->eventId,
],
);
diff --git a/api/app/Observers/OrganisationObserver.php b/api/app/Observers/OrganisationObserver.php
index ad7f9397..2aeb1f25 100644
--- a/api/app/Observers/OrganisationObserver.php
+++ b/api/app/Observers/OrganisationObserver.php
@@ -18,15 +18,18 @@ use App\Models\Organisation;
* The default seeder is idempotent โ if the org already owns an
* artist_advance schema, the call is a no-op. Safe to re-run.
*
- * Skipped during automated tests so existing FormSchema-counting
- * tests aren't perturbed; tests that need the auto-seed call
- * `ArtistAdvanceDefault::seedFor()` explicitly.
+ * Gated by `config('artist_advance.bootstrap_on_org_create')`. The
+ * config defaults to true (production behaviour); phpunit.xml flips
+ * it to false so existing FormSchema-counting tests aren't perturbed.
+ * Tests that need the auto-seed call `ArtistAdvanceDefault::seedFor()`
+ * explicitly. Tracked for removal by BACKLOG entry
+ * `TECH-OBSERVER-TEST-CONVERGENCE`.
*/
final class OrganisationObserver
{
public function created(Organisation $organisation): void
{
- if (app()->runningUnitTests()) {
+ if (! (bool) config('artist_advance.bootstrap_on_org_create', true)) {
return;
}
diff --git a/api/config/artist_advance.php b/api/config/artist_advance.php
new file mode 100644
index 00000000..09c14b53
--- /dev/null
+++ b/api/config/artist_advance.php
@@ -0,0 +1,25 @@
+ env('ARTIST_ADVANCE_BOOTSTRAP_ON_ORG_CREATE', true),
+];
diff --git a/api/phpunit.xml b/api/phpunit.xml
index 4337eea0..5b822fcd 100644
--- a/api/phpunit.xml
+++ b/api/phpunit.xml
@@ -35,6 +35,7 @@
+