| 83 | ); |
| 84 | |
| 85 | const insertConnection = ( |
| 86 | db: SqliteTestFumaDb, |
| 87 | row: { |
| 88 | readonly rowId: string; |
| 89 | readonly tenant: string; |
| 90 | readonly owner: string; |
| 91 | readonly subject: string; |
| 92 | readonly integration: string; |
| 93 | readonly name: string; |
| 94 | readonly oauthScope?: string | null; |
| 95 | }, |
| 96 | ): Effect.Effect<void> => |
| 97 | Effect.promise(async () => { |
| 98 | await db.client.execute({ |
| 99 | sql: `INSERT INTO connection ( |
| 100 | row_id, tenant, owner, subject, integration, name, template, provider, |
| 101 | item_ids, refresh_item_id, oauth_scope, last_health, created_at, updated_at |
| 102 | ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, |
| 103 | args: [ |
| 104 | row.rowId, |
| 105 | row.tenant, |
| 106 | row.owner, |
| 107 | row.subject, |
| 108 | row.integration, |
| 109 | row.name, |
| 110 | "oauth2", |
| 111 | "memory", |
| 112 | // Deliberately secret-bearing: the assertions below prove these never |
| 113 | // leave the storage layer. |
| 114 | JSON.stringify({ token: `SECRET-item-${row.rowId}` }), |
| 115 | `SECRET-refresh-${row.rowId}`, |
| 116 | row.oauthScope ?? null, |
| 117 | // A full stored verdict, upstream-derived fields included — that is |
| 118 | // what a real health check writes. This layer is entitled to read them |
| 119 | // back (see UPSTREAM_HEALTH_FIELDS); the API's projection is what keeps |
| 120 | // them off the wire. |
| 121 | JSON.stringify({ |
| 122 | status: "healthy", |
| 123 | checkedAt: 1_700_000_000_000, |
| 124 | identity: `UPSTREAM-identity-${row.rowId}@provider.test`, |
| 125 | detail: `UPSTREAM-detail-${row.rowId}`, |
| 126 | responseSample: [{ path: "user.email", value: `UPSTREAM-sample-${row.rowId}` }], |
| 127 | }), |
| 128 | Date.now(), |
| 129 | Date.now(), |
| 130 | ], |
| 131 | }); |
| 132 | }); |
| 133 | |
| 134 | /** A tenant-scoped `integration` row, inserted raw. Needed because |
| 135 | * `integrations.remove` short-circuits on an absent slug — without a real row |