002-identity-credential.xml 2.38 KB
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                   xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
                                       https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.27.xsd">

    <!--
        identity__user_credential

        Stores password hashes (and, in future, MFA secrets) for users.
        Kept in a SEPARATE table from identity__user so that:

          1. The User entity stays free of secrets and can be safely
             returned from cross-PBC facades and audit dumps.
          2. A future PBC that needs to read users (e.g. pbc-orders for
             "owner of this order") never accidentally pulls password
             hashes into its query plans.
          3. The credential row can be rotated, revoked, or deleted
             independently of the user record (e.g. on password reset).

        password_algo is recorded explicitly so the platform can support
        a graceful migration to a stronger hash function later (today:
        argon2id; tomorrow: maybe argon2id-with-newer-params).
    -->
    <changeSet id="identity-credential-001" author="vibe_erp">
        <comment>Create identity__user_credential table</comment>
        <sql>
            CREATE TABLE identity__user_credential (
                id              uuid PRIMARY KEY,
                user_id         uuid         NOT NULL UNIQUE
                                              REFERENCES identity__user(id) ON DELETE CASCADE,
                password_hash   text         NOT NULL,
                password_algo   varchar(32)  NOT NULL DEFAULT 'argon2id',
                must_change     boolean      NOT NULL DEFAULT false,
                last_changed_at timestamptz  NOT NULL,
                created_at      timestamptz  NOT NULL,
                created_by      varchar(128) NOT NULL,
                updated_at      timestamptz  NOT NULL,
                updated_by      varchar(128) NOT NULL,
                version         bigint       NOT NULL DEFAULT 0
            );
            CREATE INDEX identity__user_credential_user_id_idx
                ON identity__user_credential (user_id);
        </sql>
        <rollback>
            DROP TABLE identity__user_credential;
        </rollback>
    </changeSet>

</databaseChangeLog>