Per-project GitHub Check Run integration settings (INT-002).
installationId encryption (INT-002b follow-up)
installationId is stored AES-256-GCM encrypted at rest via
encryptString / decryptString from utils/credentialEncryption.js.
The encryption format is version-prefixed (enc:v1:…), so legacy
plaintext rows decrypt transparently — no backfill migration required;
rows re-encrypt naturally on the next upsert() call.
Cost trade-off, documented because it's surprising: installation-keyed
lookups (getByInstallationId, disableByInstallationId, disableByRepo)
can no longer use SQL WHERE installationId = ? against a deterministic
column value — AES-GCM uses a fresh random IV per encryption, so the
ciphertext for the same plaintext differs every write. These methods now
load every row, decrypt installationId, and JS-filter. This is O(n) over
the number of projects with GitHub check settings configured (one row per
project), which is small enough in practice that the indexed-lookup loss
is acceptable. If row count ever grows past ~10k, revisit with a
deterministic HMAC-based lookup column (installationIdHash) so the
encrypted blob stays randomised but lookups stay O(1).
Threat-model honesty: GitHub exposes installationId publicly in its
own UI and in every webhook payload. The encryption here is compliance
hardening for SOC 2 / ISO 27001 "encrypt all third-party identifiers at
rest" line items, not load-bearing security. The actual auth secret is
GITHUB_APP_PRIVATE_KEY (env var, never in DB). See ROADMAP.md
§ INT-002b for the full rationale and the reversal of the prior WONTFIX.
Methods
(static) disableByInstallationId(installationId) → {Array.<string>}
Disable every GitHub check settings row for an installation.
Same O(n) load-and-filter pattern as getByInstallationId — the
encrypted installationId column can't be used as a SQL predicate.
Parameters:
| Name | Type | Description |
|---|---|---|
installationId |
string | number |
Returns:
Project IDs that were disabled.
- Type
- Array.<string>
(static) disableByRepo(installationId, repo) → {Array.<string>}
Disable GitHub check settings for one repository within an installation.
Parameters:
| Name | Type | Description |
|---|---|---|
installationId |
string | number | |
repo |
string |
Returns:
Project IDs that were disabled.
- Type
- Array.<string>
(static) getByInstallationId(installationId) → {Array.<Object>}
Get all GitHub check settings rows for an installation.
Lookup cost: loads every row and JS-filters by decrypted
installationId. AES-GCM ciphertext is non-deterministic (fresh IV per
encryption) so a WHERE installationId = ? SQL filter against the
ciphertext column would never match. See the module-level doc comment
for the full rationale and the deterministic-HMAC escape hatch.
Parameters:
| Name | Type | Description |
|---|---|---|
installationId |
string | number |
Returns:
- Type
- Array.<Object>
(static) getByProjectId(projectId) → {Object|undefined}
Get GitHub check settings for a project.
Parameters:
| Name | Type | Description |
|---|---|---|
projectId |
string |
Returns:
- Type
- Object | undefined
(static) listByProjectIds(projectIds) → {Array.<Object>}
List GitHub check settings for project IDs.
Parameters:
| Name | Type | Description |
|---|---|---|
projectIds |
Array.<string> |
Returns:
- Type
- Array.<Object>
(static) upsert(settings) → {Object|undefined}
Create or update GitHub check settings for a project.
Parameters:
| Name | Type | Description | ||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
settings |
Object |
Properties
|
Returns:
- Type
- Object | undefined