anastasis

Credential backup and recovery protocol and service
Log | Files | Refs | Submodules | README | LICENSE

stasis-0002.sql (3112B)


      1 --
      2 -- This file is part of Anastasis
      3 -- Copyright (C) 2026 Anastasis SARL
      4 --
      5 -- ANASTASIS is free software; you can redistribute it and/or modify it under the
      6 -- terms of the GNU General Public License as published by the Free Software
      7 -- Foundation; either version 3, or (at your option) any later version.
      8 --
      9 -- ANASTASIS is distributed in the hope that it will be useful, but WITHOUT ANY
     10 -- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
     11 -- A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
     12 --
     13 -- You should have received a copy of the GNU General Public License along with
     14 -- ANASTASIS; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
     15 --
     16 
     17 -- Everything in one big transaction
     18 BEGIN;
     19 
     20 -- Check patch versioning is in place.
     21 SELECT _v.register_patch('stasis-0002', NULL, NULL);
     22 
     23 SET search_path TO anastasis;
     24 
     25 -- Garbage collection deletes WHERE expiration_date < $1 with no truth_uuid
     26 -- predicate, so the index must lead with expiration_date; the existing
     27 -- (truth_uuid, expiration_date) lookup index cannot serve that scan.
     28 --
     29 -- stasis-0001 already created an index of this name, as a straight duplicate
     30 -- of anastasis_challengecode_uuid_index on (truth_uuid, expiration_date).  It
     31 -- has to be dropped first: CREATE INDEX IF NOT EXISTS matches on the name
     32 -- alone and does not compare definitions, so without this DROP every provider
     33 -- that ran 0001 would silently keep the useless index, never get the one
     34 -- garbage collection needs, and still have 0002 recorded as applied.
     35 DROP INDEX IF EXISTS anastasis_challengecode_expiration_index;
     36 CREATE INDEX anastasis_challengecode_expiration_index
     37   ON anastasis_challengecode
     38   (expiration_date);
     39 COMMENT ON INDEX anastasis_challengecode_expiration_index
     40   IS 'for challenge garbage collection';
     41 
     42 -- stasis-0001 commented anastasis_recdoc_payment twice: the second one, in
     43 -- the anastasis_challenge_payment block, overwrote the recovery-document text
     44 -- with the challenge text and left anastasis_challenge_payment itself
     45 -- undocumented.  0001 is released and must stay byte-identical to what
     46 -- providers already ran, so the correction lives here.
     47 COMMENT ON TABLE anastasis_recdoc_payment
     48   IS 'Records a payment for a recovery document';
     49 COMMENT ON TABLE anastasis_challenge_payment
     50   IS 'Records a payment for a challenge';
     51 
     52 -- A TOTP code stays valid for a whole window of time steps, so without
     53 -- remembering which step was already used an observed code can simply be
     54 -- replayed while the window lasts.  RFC 6238 section 5.2 requires that a code
     55 -- be accepted at most once; this column is what makes that decidable.  It
     56 -- lives on the truth so that it is removed by the same garbage collection.
     57 ALTER TABLE anastasis_truth
     58   ADD COLUMN IF NOT EXISTS last_totp_counter INT8 NOT NULL DEFAULT 0;
     59 COMMENT ON COLUMN anastasis_truth.last_totp_counter
     60   IS 'Highest TOTP time step counter already accepted for this truth; a code for this or an earlier step is a replay and is refused. Zero means no code was accepted yet. Unused for other authentication methods.';
     61 
     62 COMMIT;