Skip to content

fix!: harden dapper providers and skip keys with null xml - #53

Merged
giammin merged 3 commits into
mainfrom
fix/review-findings
Oct 23, 2026
Merged

giammin merged 3 commits into
mainfrom
fix/review-findings

Conversation

@giammin

@giammin giammin commented Oct 23, 2026

Copy link
Copy Markdown
Owner

Fixes found in a code review of src. One commit per area; the squash commit should use the message below.

  • postgresql: InitializeDb() creates the table and the friendly-name index only when they are missing. PostgreSQL checks privileges before IF NOT EXISTS, so a role without CREATE on the schema (the default on public since PostgreSQL 15) failed on every start even when the table existed. Covered by a new test that runs InitializeDb() as a restricted role.
  • postgresql: schema and table names are limited to 45 characters together, so that ix_{schema}_{table}_friendly_name fits the 63-character identifier limit instead of being silently truncated (two tables could get the same index name).
  • sqlserver: SqlConnectionFactory is registered as a keyed service, as the PostgreSQL data source since fix(postgresql): register NpgsqlDataSource as a keyed service #48, so it no longer collides with a factory registered by the application.
  • core: a stored key with null XML is logged (SkippingMalformedKey) and skipped instead of failing the whole key ring.

README (name limits, initialization privileges, v2 migration notes) and AGENTS.md are updated.

BREAKING CHANGE: PostgreSQL schema and table names longer than 45 characters together are rejected at startup. Rename the table and its ix_{schema}_{table}_friendly_name index, then update the configuration.
BREAKING CHANGE: SqlConnectionFactory is no longer resolvable without a key. Applications that resolved it must register their own; applications that register SQLServerDataProtectionRepository themselves must call PersistKeysWithDapperInSqlServer() or pass the connection factory explicitly.

InitializeDb checks pg_tables and pg_indexes before creating the table and
the friendly-name index: PostgreSQL checks privileges before IF NOT EXISTS,
so a role without CREATE on the schema failed on every start even when the
table existed.

The validator limits the schema and table names to 45 characters together,
so that the derived index name fits the 63-character identifier limit
instead of being silently truncated.

BREAKING CHANGE: PostgreSQL schema and table names longer than 45 characters
together are rejected at startup. Rename the table and its
ix_{schema}_{table}_friendly_name index, then update the configuration.
The provider registered the public SqlConnectionFactory as an unkeyed
singleton, so a factory registered by the application either replaced the
keys connection or received it, depending on the registration order. It is
now registered under an internal service key, as the PostgreSQL data source.

BREAKING CHANGE: SqlConnectionFactory is no longer resolvable without a key.
Applications that resolved it must register their own; applications that
register SQLServerDataProtectionRepository themselves must call
PersistKeysWithDapperInSqlServer() or pass the connection factory explicitly.
DataProtectionKey.Xml is required but not enforced at runtime. A null value
made XElement.Parse throw ArgumentNullException, which failed the whole key
ring instead of skipping the row. It is now handled as an empty, malformed
document: logged as SkippingMalformedKey and skipped.
@giammin
giammin merged commit 8c0b501 into main Oct 23, 2026
1 check passed
@giammin

giammin commented Oct 23, 2026

Copy link
Copy Markdown
Owner Author

Rebased and merged to have the commits in history instead of using the usual squash

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant