bewaking-adcd605d-d44a

job succeeded

time taken
7 seconds
started at
Wed Oct 14 14:41:47 2026
updated at
Wed Oct 14 14:41:54 2026
log uuid
adcd605d-d44a-495f-b205-2796f5d0b277
inspect the job's lambda expression
(lambda()
  `((task . ("maak-test" "maak-deploy"))
    (project . "bewaking")
    (branch-name . "trunk")
    (clone-url . "https://codeberg.org/jjba23/bewaking.git")))
starting new job...


→ running command: cd "/etc/byggsteg/job-clone//bewaking/trunk" && git reset --hard && git pull

HEAD is now at 8bc1087 update: Test library
From https://codeberg.org/jjba23/bewaking
   8bc1087..67774e2  trunk      -> origin/trunk
 * [new tag]         v0.4.1     -> v0.4.1
Updating 8bc1087..67774e2
Fast-forward
 .woodpecker/tag-bumper.yaml | 49 ---------------------------------------------
 1 file changed, 49 deletions(-)
 delete mode 100644 .woodpecker/tag-bumper.yaml

→ running command: cd /etc/byggsteg/job-clone/bewaking/trunk && uname -a

Linux wolk-jjba 7.1.5-gnu #1 SMP PREEMPT_DYNAMIC 1 x86_64 GNU/Linux

→ running command: cd /etc/byggsteg/job-clone/bewaking/trunk && git log --name-status HEAD^..HEAD

commit 67774e269936da12004c18b0fe00e41b625e07d1
Author: Josep Bigorra <jjbigorra@gmail.com>
Date:   Wed Oct 14 14:35:55 2026 +0200

    ci: Simplify CI workflows

D       .woodpecker/tag-bumper.yaml

→ running command: cd /etc/byggsteg/job-clone/bewaking/trunk && maak test


scanning directories for unit tests...
scanning present working directory for unit tests...

shuffled the files with seed 844052010 (replay with VERITAS_SEED=844052010)

found unit tests: (bewaking-spec.scm crypto-spec.scm web-spec.scm cli-spec.scm password-spec.scm)


running unit tests from file: bewaking-spec.scm, entrypoint: spec


owner-details: ((id . "444959d3-7a8e-455e-b608-31e35145a2fa") (email . "someone@jointhefreeworld.org") (name . "Legolas son of Thandruil") (permissions byggsteg:modify-permissions byggsteg:job-create byggsteg:job-delete byggsteg:profile-create byggsteg:profile-delete byggsteg:user-create byggsteg:user-delete))

generate-token: BWK3.default.1791981711.-.01e7cf0a1a9524ac62873ff7e5b4eb9b315927618a8a2d24747ef7515ae182ee392deef444b3350ec6f6a02b2bd71bc2cf7b0bd4800a4b556827aa0bb91f362bd60ec42372d8f88e64f1a8697d7bd939d0067ae290df004a681f0eaedc95a6ddc953366a91e679f10a1c0f2bf5eb9bb4bdb928b497c036d634de2116510526a1211efe65210d9590edb731f08d287af66074c48e0e89340350980072cdcc1b2d517651b266bef0da65472d8f7263746212122eed70cf9cf81c559d076cfc81fd25009c41f67fc93cb4f63a90d4ed4d0430cd2babc75a325e604152bef2dc484171d33535b656626d1fe3a82240540be4c26831512076651e6c8414bada6f08e2ebba0deea8e3a80d194201a698a822a6b6871daacf9ef46eeebd041a0aa7d79cf192e25c43d8d5bd959bf2322dec1636abb54827fcc4d98313e90f345568286e298fe9f91dbee95586eeb817663aa5a8816880d43f4e1e1f085a7dcb1165797db6a22b95b71fac2cab6bd6b4bc0a0d2232dd1da8752731c7b28ac2325f070dfa7fe75e83b52ac825a6430b587067e7607c58226475c4c85312135cf5ae91767655feab3a80540fe1515b8dc62d80e3a59d0f09a0bad7b0e86e3efab051af010bdb0aee1ca4ad8b620045306f3dce2168703408cd8328bec05f19975540167f05b696057032591b3b47b0e6128dda3c0cbebdd3eeee38c97dc1b4af9945064cd5e0bf1c39774a4f799e53c72ee6f0b1c569afa67c97cbef92c866ef4c3428d53b0f8ee3b0b83b4b5d645c8cf3d91192614a69cbdf477cb2bed08c79e0218d8cf811a92bec03731480798d3b5930efcb8c2615bd4aac46b33360d2f99d9ef0a02b861a7048ac5a064a8dd2b91298ea774c77777f67ef2bfad5815ffcaff3fa1e070a3dd0fcc393a3ac9ff3807f00dab99ec7d482e7a30c13a87c0f19ee2371f4cda6b27dffd083e5194b1c875f55edb52b99f341aa0228dffa1af96b455eaf191ef9830bc144776f3b06c806a10dbabb7b5852e644efe34f51bb29aea826210757b3f4aad7c9b12146cadab5f67c83ee3d3aab37ec4c77dfb1a3e5936e7a9b1e135a559a58fbe1a7a5c6ea348c70915fe9d51812bb5538d0814e3e2a8bdd33993c89c568b9084e4f3fc71f678b66a1ea09814c9a1fccf298e54c6c663da4e2f7b0c5c56d745feee2d891c22d0165b933a65acbd385245cb0d5745bb09d87c9fc17c43844d8e5a8b688064f6e51767f808ca63399497869d68a0a6d156852e0288a3593d39c7c1d4666ea36b987014c76005ee36f81302e29229b
error decrypting token: misc-error: (#f ~A (bewaking: the sealed data could not be opened: unknown, retired or wrong key, or the data was altered.) #f)error decrypting token: misc-error: (#f ~A (open-envelope: not a bewaking envelope (expected BWK3).) #f)
owner-details: ((id . "444959d3-7a8e-455e-b608-31e35145a2fa") (email . "someone@jointhefreeworld.org") (name . "Legolas son of Thandruil") (permissions byggsteg:modify-permissions byggsteg:job-create byggsteg:job-delete byggsteg:profile-create byggsteg:profile-delete byggsteg:user-create byggsteg:user-delete))

generate-token: BWK3.default.1791981711.-.018481981e2f8785aec95b02b24d4c6a405ea4b14e7bb8cb199582eb4648e6056f249a33eb0f07c51f50d1ebc881b769e9449d4036827beed523642f97ea96d787702a6298343320baa3dbcea0afa8d2c3ff1b7bb50eb13fc306b253985110a4d62561f24685f594535c39ea2cb4ffbf03d97b0ea2d18a5d9ccf302a445ed65b87257843035befb26fa518fcfd65d7dc5e601401a73adc29e89c1c9c4bd09009265e26a16e8f7ebc87bdd3139f1eb3657e9604667996a9cc1b10a8d6fb4d250eaee8c861e6b61008c1b62cb5b9d7eeab2120d3aa2e1e5368d3975aaac200f1ba6d39bda85acd5d1d8bc0947a49180a201c1c94a6c23950ff0e6b2bb1f45ae73153f33af3d051027ffb5a9d5cbdecca32a98621c177f1a75d6d1c903c57ffa49069af862d1403301cda6c0aa30d44b7ece72cde79eaa108458db6050687af998b7ccb81ba57f34979ab05812612b1286272dd335c2ae23148ccff0334abc4098d99dcbe0d9175ba0c2c879ce705ba16be91a70bd8c365f95e15919bb9f1adb31e94973e52232738e659e344b04d35499b16768384a577473976870df44aa06e57d388b23562d309a68a460dd488ad008d57308c0fd104249d2e707515c384c5c50c22f19d12a8535f577c338a544a28321acc0f713e70080db6945a49fa158399a44db29bfd9ad98889f98a3458d7e988f861172049e168cb70167ea187619bcec41f42f127a080ac2becc50a707a4725de408caf54947f1fb9bab25af550b0b984ce317c0cc02f98644b24f8299eee685b89e3cdf9b945af35ee3e7d996e32e1e1b1693b7d80e8f99d3d17ef458daca232a13caa4277b6d18a63dafa1db72a8aea4e17516358b676d579867664d3e461548e5c06aa16efeae9c836093157595a6b1b3a329d4f48d59fb473ebffea74db2ca9d4a01aceff36e61dc07d15c3a273e72eca31cfe3728091b2167c3fe3bf1e83d4a8989a3564edc9308af94684be721a08a5f6e1b4523df8de31544e1fa4c4e02020e49dfd15aa63f78baebf60b3c60ef2f1ec62b64f3de397c93fa2d6ec096580cbfc275501989d89b78c98dcf41c40799defa72e40a5f822407deae133b29a5167377fadb370b79f48d45d287a44f104723ec5cdfc5a2ceeaff4f2bb5dc1df23ce311d475d3acd4c67a92e2613bf368d1d9401f16e093c1d21ed18a68cf1724ac059a4f235fbbf7dbeefb297268571a7bc843301fd10beb85ea2fd6bf6a168a8f881ac156737e83aff60a2e0d736aa8399c9cba678bf7b6ddbad98f4074373729554c942be7942

decoded: ((token-type . bewaking-token) (token-id . 3ff46a92-f947-41c4-b60b-3410f02874c1) (token-created-at . 1791981711) (token-expires-at . 1792586511) (owner-id . 444959d3-7a8e-455e-b608-31e35145a2fa) (owner-email . someone@jointhefreeworld.org) (owner-name . Legolas son of Thandruil) (owner-permissions byggsteg:modify-permissions byggsteg:job-create byggsteg:job-delete byggsteg:profile-create byggsteg:profile-delete byggsteg:user-create byggsteg:user-delete))
error decrypting object: misc-error: (#f ~A (bewaking: the sealed data could not be opened: unknown, retired or wrong key, or the data was altered.) #f)error decrypting token: misc-error: (#f ~A (bewaking: the sealed data could not be opened: unknown, retired or wrong key, or the data was altered.) #f)error decrypting object: misc-error: (#f ~A (bewaking: the sealed data could not be opened: unknown, retired or wrong key, or the data was altered.) #f)error decrypting token: misc-error: (#f ~A (open-envelope: not a bewaking envelope (expected BWK3).) #f)error decrypting object: misc-error: (#f ~A (open-envelope: not a bewaking envelope (expected BWK3).) #f)error decrypting token: misc-error: (#f ~A (open-envelope: not a bewaking envelope (expected BWK3).) #f)error decrypting object: misc-error: (#f ~A (open-envelope: not a bewaking envelope (expected BWK3).) #f)error decrypting object: misc-error: (#f ~A (bewaking: the sealed data could not be opened: unknown, retired or wrong key, or the data was altered.) #f)error decrypting object: misc-error: (#f ~A (bewaking: the sealed data could not be opened: unknown, retired or wrong key, or the data was altered.) #f)error decrypting token: misc-error: (#f ~A (open-envelope: the sealed data expired at 1000 (key 'default').) #f)error decrypting object: misc-error: (#f ~A (open-envelope: the sealed data expired at 1000 (key 'default').) #f)
?? info - shuffled with seed 844052010 (replay with VERITAS_SEED=844052010)
+----------------------------------------------+
[? suite] Garbling and Ungarbling
  [? test] garble-ungarble
    ? got: ow
    ? got: dlrow
    ? got: dlrow olleh
    ? got: hello world
    ? got: w
    ? got: np3ld1h3o9p2f18plzqjl8ghyi7ak9wdald8j6xcbd4y33pwbml62p837y750qm6incwwjubxwm4fl7tprvdr0kwwto1k6lsnhxr529rbga47em1aq7evwknolg6r5gp
    ? got: lrow
    ? got: row
+----------------------------------------------+
[? suite] Permissions
  [? test] has-needed-permissions?
    ? got: #t
    ? got: #t
    ? got: #f
    ? got: #f
    ? got: #f
    ? got: #f
    ? got: #t
    ? got: #t
+----------------------------------------------+
[? suite] Lossless Token Decryption
  [? test] lossless-token
    [?? assert] works properly with correct details
    ? got: #t
+----------------------------------------------+
[? suite] Generic object encryption
  [? test] encrypt-object and decrypt-object
    [?? assert] round-trips a plain string payload
    ? got: just a string
    [?? assert] round-trips a list payload
    ? got: (1 2 3)
    [?? assert] fails gracefully with a wrong signing key
    ? got: #f
    [?? assert] round-trips a number payload
    ? got: 1234
  [? test] decrypted data is data, never code
    [?? assert] Guile refuses the #. read-eval syntax
    ? got: #t
    [?? assert] a sealed payload that looks like code stays a string
    ? got: #.(+ 1 2)
+----------------------------------------------+
[? suite] generate-token
  [? test] works properly with correct details
    ? got: #t
+----------------------------------------------+
[? suite] Token expiry
  [? test] is-token-expired?
    [?? assert] a malformed token-expires-at raises an error
    ? success catching error: misc-error: (#f is-token-expired?: Token is invalid. Missing or malformed 'token-expires-at' () #f)
    [?? assert] a token whose expiry is in the future is not expired
    ? got: #f
    [?? assert] a far-future token is not expired
    ? got: #f
    [?? assert] a missing token-expires-at raises an error
    ? success catching error: misc-error: (#f is-token-expired?: Token is invalid. Missing or malformed 'token-expires-at' () #f)
    [?? assert] a token whose expiry is in the past is expired
    ? got: #t
+----------------------------------------------+
[? suite] Sealed envelope (versioned, authenticated)
  [? test] key rotation with a keyring
    [?? assert] a keyring seals and opens by key id
    ? got: #t
  [? test] knowing the format is not knowing the plaintext
    [?? assert] the format is not hidden, only the content is
    ? got: #t
    [?? assert] the plaintext, its Base16 and its Base64 do not appear in the envelope
    ? got: #t
    [?? assert] the public metadata is exactly what is authenticated
    ? got: (version key-id created-at expires-at)
  [? test] data that is not a BWK3 envelope is refused
    [?? assert] a bare Base16 object is refused
    ? got: #f
    [?? assert] recognition is a version-tag check, not a structure check
    ? got: #t
    [?? assert] an unsupported version raises rather than being guessed at
    ? got: #t
    [?? assert] a pre-versioning bare Base16 token is refused
    ? got: #f
    [?? assert] a truncated envelope is refused when it is opened
    ? got: #t
    [?? assert] an unknown envelope version is not recognised
    ? got: #f
    [?? assert] a BWK3 envelope carrying an extra MAC field is refused
    ? got: #t
    [?? assert] arbitrary text is not an envelope
    ? got: #f
  [? test] seal-envelope and open-envelope
    [?? assert] a wrong signing key fails the cipher check
    ? got: #t
    [?? assert] the module exposes the current format version
    ? got: BWK3
    [?? assert] the plaintext round-trips
    ? got: top secret payload
    [?? assert] passing a MAC key to open-envelope is refused, not ignored
    ? got: #t
    [?? assert] the result is a versioned envelope
    ? got: #t
    [?? assert] BWK3 is the only version produced and read
    ? got: (BWK3)
    [?? assert] the envelope starts with the version tag
    ? got: #t
    [?? assert] a tampered envelope fails the integrity check
    ? got: #t
  [? test] editing a genuine envelope never yields a plaintext
    [?? assert] and every mutation of a real sealed object too
    ? got: #t
    [?? assert] every single-digit mutation of a real envelope is refused
    ? got: #t
  [? test] a refusal never says which key id the keyring configures
    [?? assert] and it does not name a configured key id either
    ? got: #f
    [?? assert] an expired genuine envelope is still told apart, since it authenticated first
    ? got: #f
    [?? assert] an unknown key id and a tampered body fail identically
    ? got: (misc-error #f ~A (bewaking: the sealed data could not be opened: unknown, retired or wrong key, or the data was altered.) #f)
    [?? assert] a keyring with no matching entry fails identically
    ? got: (misc-error #f ~A (bewaking: the sealed data could not be opened: unknown, retired or wrong key, or the data was altered.) #f)
    [?? assert] a key that is not active yet fails identically
    ? got: (misc-error #f ~A (bewaking: the sealed data could not be opened: unknown, retired or wrong key, or the data was altered.) #f)
    [?? assert] the refusal is a refusal, not an accidental success
    ? got: #t
    [?? assert] the refusal does not name the key id it could not resolve
    ? got: #f
    [?? assert] a retired key fails identically
    ? got: (misc-error #f ~A (bewaking: the sealed data could not be opened: unknown, retired or wrong key, or the data was altered.) #f)
    [?? assert] nor does it carry any key material
    ? got: #f
  [? test] the requested key id is embedded in generated tokens
    [?? assert] the token carries the key id
    ? got: #t
  [? test] the same plaintext never seals to the same value
    [?? assert] a fresh salt and nonce make each envelope unique
    ? got: #t
    [?? assert] equal objects seal to different strings
    ? got: #f
  [? test] tokens and objects are envelopes and reject tampering
    [?? assert] a tampered object is rejected
    ? got: #t
    [?? assert] a tampered token is rejected
    ? got: #t
    [?? assert] generated tokens are enveloped
    ? got: #t
    [?? assert] sealed objects are enveloped
    ? got: #t
  [? test] no reader is left for the earlier formats
    [?? assert] no metadata is read out of a BWK2 envelope
    ? got: #f
    [?? assert] no metadata is read out of a BWK1 envelope
    ? got: #f
    [?? assert] a BWK1 object is refused likewise
    ? got: #f
    [?? assert] a BWK2 envelope is not recognised
    ? got: #f
    [?? assert] a BWK1 envelope is not recognised
    ? got: #f
    [?? assert] a BWK2 envelope with no expiry is not recognised
    ? got: #f
    [?? assert] an unreadable envelope is never reported as live
    ? got: #f
    [?? assert] a BWK2 token is refused even with the keys that sealed it
    ? got: #f
+----------------------------------------------+
[? suite] Decryption
  [? test] decrypt-token
    [?? assert] fails gracefully when signing key is not valid
    ? got: #f
    [?? assert] works properly with valid token
    ? got: #t
    [?? assert] fails gracefully when token is not valid
    ? got: #f
+----------------------------------------------+
[? suite] Token validity helpers
  [? test] token-remaining-seconds and token-valid?
    [?? assert] remaining seconds is positive for a live token
    ? got: #t
    [?? assert] a missing expiry raises an error
    ? success catching error: misc-error: (#f token-remaining-seconds: Token is invalid. Missing or malformed 'token-expires-at' () #f)
    [?? assert] a freshly generated token is not expired
    ? got: #f
    [?? assert] remaining seconds is negative for an expired token
    ? got: #t
+----------------------------------------------+
[? suite] Envelope metadata (key id, created-at, expiry)
  [? test] keyring validity windows enforce rotation
    [?? assert] a key inside its window seals and opens
    ? got: #t
    [?? assert] a key past not-after cannot open data
    ? got: #t
    [?? assert] no keyring is needed to read metadata
    ? got: #t
    [?? assert] a key before not-before cannot seal data
    ? got: #t
  [? test] a malformed envelope is rejected
    [?? assert] a body that is not hexadecimal is refused
    ? got: #t
    [?? assert] a non-numeric created-at is refused
    ? got: #t
    [?? assert] a missing body is refused
    ? got: #t
    [?? assert] a truncated body is refused
    ? got: #t
    [?? assert] an empty key id is refused
    ? got: #t
    [?? assert] sealing a non-string plaintext is refused
    ? got: #t
    [?? assert] sealing without a signing key is refused
    ? got: #t
  [? test] ttl-seconds records an absolute expiry
    [?? assert] the envelope is live before its expiry
    ? got: #f
    [?? assert] expires-at is created-at plus the ttl
    ? got: 4600
    [?? assert] created-at is the requested timestamp
    ? got: 1000
    [?? assert] the envelope is expired after its expiry
    ? got: #t
  [? test] expiry is enforced when opening
    [?? assert] max-age-seconds enforces a rotation policy
    ? got: #t
    [?? assert] an expired envelope is refused
    ? got: #t
    [?? assert] enforce-expiry? #f still opens it
    ? got: ttl payload
  [? test] metadata is reported without any key
    [?? assert] metadata is only read from envelopes
    ? got: #f
    [?? assert] created-at is a Unix timestamp
    ? got: #t
    [?? assert] the format version is reported
    ? got: BWK3
    [?? assert] a malformed BWK3 envelope reports no metadata
    ? got: #f
    [?? assert] there is no expiry unless one was requested
    ? got: #f
    [?? assert] the key id is reported
    ? got: default
    [?? assert] an envelope of a dropped format reports no metadata
    ? got: #f
  [? test] expired tokens and objects are refused
    [?? assert] a token sealed with a past expiry is refused
    ? got: #t
    [?? assert] expiry auditing ignores non-envelopes
    ? got: #f
    [?? assert] an object sealed with a past expiry is refused
    ? got: #t
  [? test] the metadata is authenticated
    [?? assert] relabelling the version is refused
    ? got: #t
    [?? assert] editing created-at in a BWK3 envelope breaks its tag
    ? got: #t
    [?? assert] extending the expiry in the envelope breaks the tag
    ? got: #t
    [?? assert] editing the body breaks the tag
    ? got: #t
    [?? assert] editing the key id breaks the tag
    ? got: #t
    [?? assert] removing the expiry marker breaks the tag
    ? got: #t
    [?? assert] backdating created-at breaks the tag
    ? got: #t
  [? test] invalid sealing options are rejected
    [?? assert] expires-at and ttl-seconds are mutually exclusive
    ? got: #t
    [?? assert] a key id containing a dot is rejected
    ? got: #t
    [?? assert] a non-integer ttl-seconds is rejected
    ? got: #t
?? info - ran 10 tasks in: 0 seconds, 22908 microseconds

running unit tests from file: crypto-spec.scm, entrypoint: spec


?? info - shuffled with seed 844052010 (replay with VERITAS_SEED=844052010)
+----------------------------------------------+
[? suite] Argon2id key derivation (RFC 9106)
  [? test] the RFC 9106 Argon2id vector is reproduced
    [?? assert] password 32x01, salt 16x02, secret 8x03, data 12x04, m=32, t=3, p=4
    ? got: 0d640df58d78766c08c037a34a8b53c9d01ef0452d75b65eb52520e96b01e659
  [? test] every parameter changes the derived bytes
    [?? assert] a different salt gives a different tag
    ? got: #f
    [?? assert] a different passphrase gives a different tag
    ? got: #f
    [?? assert] a different pass count gives a different tag
    ? got: #f
  [? test] invalid parameters are rejected
    [?? assert] zero lanes is refused
    ? got: #t
    [?? assert] a non-integer memory cost is refused
    ? got: #t
    [?? assert] zero passes is refused
    ? got: #t
    [?? assert] this libgcrypt provides Argon2
    ? got: #t
    [?? assert] less than 8 KiB per lane is refused
    ? got: #t
    [?? assert] a non-bytevector secret is refused
    ? got: #t
+----------------------------------------------+
[? suite] Randomness
  [? test] random-bytes returns genuinely fresh bytes
    [?? assert] the default length is the OpenSSL salt length
    ? got: 8
    [?? assert] the requested length is honoured
    ? got: 32
    [?? assert] two calls do not return the same bytes
    ? got: #t
    [?? assert] a draw is not a constant
    ? got: #f
    [?? assert] a draw is not all zeroes
    ? got: #t
+----------------------------------------------+
[? suite] Base16 encoding
  [? test] malformed input is rejected
    [?? assert] embedded whitespace raises
    ? success catching error: misc-error: (#f bewaking: malformed hexadecimal input (odd number of digits). () #f)
    [?? assert] non-hexadecimal characters raise
    ? success catching error: misc-error: (#f bewaking: malformed hexadecimal input. () #f)
    [?? assert] an odd number of digits raises
    ? success catching error: misc-error: (#f bewaking: malformed hexadecimal input (odd number of digits). () #f)
  [? test] known encodings
    [?? assert] the empty string encodes to nothing
    ? got: 
    [?? assert] a word encodes byte per byte
    ? got: 626577616b696e67
    [?? assert] lowercase hex digits are produced
    ? got: 68656c6c6f
  [? test] decoding accepts both cases
    [?? assert] encoding then decoding is lossless
    ? got: hello
    [?? assert] uppercase hex decodes too
    ? got: hello
    [?? assert] lowercase hex decodes
    ? got: hello
+----------------------------------------------+
[? suite] PBKDF2-HMAC-SHA256
  [? test] the key and IV material OpenSSL derives
    [?? assert] 48 bytes over 10000 iterations, as `openssl kdf' reports
    ? got: cb14e1e1f7ac2fe57f2fcaa462d4ad903867450d9778d2ccf939d8ad3cb99982e0edbd06820c0a636f6fd53d4be339fd
  [? test] published password/salt vectors
    [?? assert] one iteration
    ? got: 120fb6cffcf8b32c43e7225256c4f837a86548c92ccc35480805987cb70be17b
    [?? assert] 4096 iterations
    ? got: c5e478d59288c841aa530db6845c4c8d962893a001ce4e11a4963873aa98134a
    [?? assert] two iterations
    ? got: ae4d0c95af6b46d32d0adff928f06dd02a303f8ef3c251dfd6e2d85a95474c43
+----------------------------------------------+
[? suite] Key-derivation specifications
  [? test] unsupported specifications are refused
    [?? assert] an unknown KDF name is refused
    ? got: #t
    [?? assert] an out-of-range Argon2id memory cost is refused
    ? got: #t
    [?? assert] a PBKDF2 cost the OpenSSL format cannot record is refused
    ? got: #t
    [?? assert] a string is not a KDF specification
    ? got: #t
  [? test] the default is PBKDF2 with its fixed cost
    [?? assert] the module default names PBKDF2
    ? got: pbkdf2
    [?? assert] its iteration count is the OpenSSL one
    ? got: 10000
  [? test] Argon2id defaults are filled in and reported
    [?? assert] the defaults are 64 MiB, 3 passes, 1 lane
    ? got: ((kdf . argon2id) (memory-kib . 65536) (iterations . 3) (parallelism . 1))
    [?? assert] given parameters are kept and the rest defaulted
    ? got: ((kdf . argon2id) (memory-kib . 262144) (iterations . 4) (parallelism . 1))
+----------------------------------------------+
[? suite] HMAC-SHA256 (RFC 4231)
  [? test] RFC 4231 test case 1
    [?? assert] a 20-byte key of 0x0b over "Hi There"
    ? got: b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7
  [? test] RFC 4231 test case 2
    [?? assert] the key "Jefe" over its test message
    ? got: 5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843
  [? test] the digest is 32 bytes and key-sensitive
    [?? assert] changing the key changes the MAC
    ? got: #f
    [?? assert] 64 hexadecimal digits, i.e. 32 bytes
    ? got: 64
+----------------------------------------------+
[? suite] OpenSSL-compatible sealing
  [? test] failures are reported rather than ignored
    [?? assert] a truncated body raises rather than returning garbage
    ? got: #t
    [?? assert] input that is not Base64 raises
    ? got: #t
    [?? assert] the wrong key raises for OpenSSL-produced data too
    ? got: #t
    [?? assert] Base64 without a Salted__ header raises
    ? got: #t
    [?? assert] the wrong key raises
    ? got: #t
  [? test] data produced by OpenSSL itself can be opened
    [?? assert] an openssl-encrypted string, random salt and all
    ? got: a secret that openssl sealed
  [? test] round-trips
    [?? assert] a longer payload round-trips
    ? got: a secret that openssl sealed
    [?? assert] one padded block follows the 16-byte Salted__ header
    ? got: 32
    [?? assert] the empty string round-trips
    ? got: 
  [? test] the salt must be 8 bytes
    [?? assert] a short salt raises
    ? success catching error: misc-error: (#f bewaking: a PBKDF2 salt must be 8 bytes long. () #f)
  [? test] a fixed-salt vector matches OpenSSL byte for byte
    [?? assert] and it decrypts back
    ? got: bewaking
    [?? assert] the ciphertext of a known salt and key
    ? got: U2FsdGVkX18AAQIDBAUGByAGpafcjamTQUX3eOyvQUE=
+----------------------------------------------+
[? suite] Authenticated payloads (AES-256-GCM)
  [? test] the payload is byte for byte the reference implementation's
    [?? assert] Argon2id with its parameters recorded, likewise
    ? got: 020000200000000001000000010707070707070707070707070707070709090909090909090909090996b424d50c29974261cc56650752a5237f7528271202d70046f0bc49c8c0bfefb86150c0b946a554a1590bec6d5f03409bbff197af7d782651
    [?? assert] PBKDF2-HMAC-SHA256, as Python's cryptography seals it
    ? got: 010707070707070707070707070707070709090909090909090909090915d0ed647041883a00a39c1a98153992e43396ca2ef78f30cf603552820a8ed81e320d38a87aee14ad4a7f41b2df7b369d6614500294e59e58
  [? test] the tag refuses every alteration
    [?? assert] a flipped ciphertext digit is refused
    ? got: #t
    [?? assert] the wrong key is refused
    ? got: #t
    [?? assert] a flipped tag digit is refused
    ? got: #t
    [?? assert] different associated data is refused
    ? got: #t
    [?? assert] a truncated payload is refused
    ? got: #t
    [?? assert] an unknown key-derivation id is refused, not guessed at
    ? got: #t
  [? test] fresh salt and nonce still round-trip
    [?? assert] a payload sealed without it does not open with it
    ? got: #t
    [?? assert] and so does an Argon2id one
    ? got: #t
    [?? assert] a payload sealed with random salt and nonce opens
    ? got: #t
    [?? assert] associated data is optional: empty means none
    ? got: #t
  [? test] hexadecimal that stands for bytes decodes to bytes
    [?? assert] and keeps the raw octets, which base16-decode cannot
    ? got: 255
    [?? assert] base16->bytes returns a bytevector
    ? got: #t
  [? test] the payload records which derivation to use
    [?? assert] PBKDF2 is identified by its own id
    ? got: 1
    [?? assert] Argon2id is identified by a different id
    ? got: 2
    [?? assert] the memory cost is recorded, in KiB
    ? got: 8192
    [?? assert] the lane count is recorded
    ? got: 1
    [?? assert] the pass count is recorded
    ? got: 1
+----------------------------------------------+
[? suite] Base64 encoding
  [? test] decoding is tolerant of line breaks
    [?? assert] encoding then decoding is lossless
    ? got: hello world
    [?? assert] a trailing newline is ignored
    ? got: hello
  [? test] malformed input is rejected
    [?? assert] non-alphabet characters raise
    ? success catching error: misc-error: (#f bewaking: malformed base64 input. () #f)
    [?? assert] a truncated group raises
    ? success catching error: misc-error: (#f bewaking: malformed base64 input (bad length or padding). () #f)
    [?? assert] an impossible amount of padding raises
    ? success catching error: misc-error: (#f bewaking: malformed base64 input (bad length or padding). () #f)
    [?? assert] data after padding raises
    ? success catching error: misc-error: (#f bewaking: malformed base64 input (data after padding). () #f)
  [? test] RFC 4648 test vectors
    [?? assert] five bytes of input
    ? got: Zm9vYmE=
    [?? assert] one byte of input
    ? got: Zg==
    [?? assert] three bytes of input
    ? got: Zm9v
    [?? assert] six bytes of input
    ? got: Zm9vYmFy
    [?? assert] four bytes of input
    ? got: Zm9vYg==
    [?? assert] two bytes of input
    ? got: Zm8=
    [?? assert] empty
    ? got: 
+----------------------------------------------+
[? suite] Sealed payloads (key derivation is recorded)
  [? test] sizes and headers are validated
    [?? assert] a 16-byte PBKDF2 salt is refused
    ? got: #t
    [?? assert] a payload with no known header is refused
    ? got: #t
    [?? assert] an 8-byte Argon2id salt is refused
    ? got: #t
  [? test] an Argon2id payload records its derivation and parameters
    [?? assert] the pass count is recorded
    ? got: 1
    [?? assert] the lane count is recorded
    ? got: 1
    [?? assert] the memory cost is recorded, in KiB
    ? got: 8192
    [?? assert] the header names the derivation
    ? got: Argon2id
  [? test] both readers keep their contracts
    [?? assert] openssl-decrypt refuses what the OpenSSL CLI could not read
    ? got: #t
    [?? assert] kdf-decrypt opens payloads produced by OpenSSL
    ? got: #t
  [? test] tampering with the recorded parameters is not honoured
    [?? assert] a changed pass count no longer decrypts
    ? got: #t
  [? test] an Argon2id payload round-trips and resists the wrong key
    [?? assert] the same key opens it
    ? got: #t
    [?? assert] another key does not
    ? got: #t
  [? test] the default KDF keeps the OpenSSL layout byte for byte
    [?? assert] a fixed-salt PBKDF2 payload equals OpenSSL's own output
    ? got: #t
+----------------------------------------------+
[? suite] Authenticated payload hygiene
  [? test] an empty plaintext is still authenticated
    [?? assert] the empty plaintext round-trips
    ? got: #t
    [?? assert] even an empty payload carries a salt, a nonce and a tag
    ? got: #t
  [? test] the recorded derivation cost is bounded before it is spent
    [?? assert] a memory cost above the cap is refused, not allocated
    ? got: #t
    [?? assert] less than 8 KiB per lane is refused
    ? got: #t
    [?? assert] a lane count above the cap is refused
    ? got: #t
    [?? assert] a cost inside the bounds is derived, then fails the tag: the bound is not a blanket refusal
    ? got: #t
    [?? assert] a zero pass count is refused
    ? got: #t
  [? test] every payload uses a fresh salt and nonce
    [?? assert] the recorded nonces differ as well
    ? got: #f
  [? test] the associated data is authenticated but not stored
    [?? assert] the associated data does not appear in the payload
    ? got: #f
    [?? assert] one extra associated-data byte breaks the tag
    ? got: #t
  [? test] the salt and the nonce are used, not decorative
    [?? assert] editing a salt digit breaks the tag
    ? got: #t
    [?? assert] editing an Argon2id parameter digit is refused
    ? got: #t
    [?? assert] editing a nonce digit breaks the tag
    ? got: #t
+----------------------------------------------+
[? suite] Derived key material
  [? test] an unknown derivation is refused
    [?? assert] no other function can be named
    ? got: #t
  [? test] PBKDF2 key material is the PBKDF2 derivation's
    [?? assert] the requested length is produced
    ? got: 32
    [?? assert] derive-key-material agrees with the primitive it names
    ? got: 25ff9d4852ea4ea0ff9caf7aa33ed9e25f8d8a4eb2915445e0ff398292d67473
  [? test] Argon2id key material honours its parameters
    [?? assert] the full key-and-IV length can be derived
    ? got: 48
    [?? assert] changing the pass count changes the material
    ? got: #t
    [?? assert] changing the passphrase changes the material
    ? got: #t
+----------------------------------------------+
[? suite] Encodings of raw bytes
  [? test] Base16 round-trips arbitrary bytevectors
    [?? assert] bytes that are not valid UTF-8 survive the round trip
    ? got: #t
    [?? assert] the empty bytevector round-trips
    ? got: #t
  [? test] Base64 round-trips arbitrary bytevectors
    [?? assert] bytes that are not valid UTF-8 survive the round trip
    ? got: 3
?? info - ran 13 tasks in: 0 seconds, 29669 microseconds

running unit tests from file: web-spec.scm, entrypoint: spec

error decrypting token: misc-error: (#f ~A (bewaking: the sealed data could not be opened: unknown, retired or wrong key, or the data was altered.) #f)error decrypting token: misc-error: (#f ~A (bewaking: malformed BWK3 envelope (created-at)) #f)error decrypting token: misc-error: (#f ~A (open-envelope: not a bewaking envelope (expected BWK3).) #f)error decrypting token: misc-error: (#f ~A (bewaking: the sealed data could not be opened: unknown, retired or wrong key, or the data was altered.) #f)error decrypting object: misc-error: (#f ~A (bewaking: the sealed data could not be opened: unknown, retired or wrong key, or the data was altered.) #f)error decrypting token: misc-error: (#f ~A (bewaking: the sealed data could not be opened: unknown, retired or wrong key, or the data was altered.) #f)error decrypting token: misc-error: (#f ~A (bewaking: the sealed data could not be opened: unknown, retired or wrong key, or the data was altered.) #f)
?? info - shuffled with seed 844052010 (replay with VERITAS_SEED=844052010)
+----------------------------------------------+
[? suite] Web chapter: sign-in seals a session into a cookie
  [? test] a verified user gets a sealed session cookie
    [?? assert] the cookie value is a BWK3 envelope
    ? got: #t
    [?? assert] (c) path "/" applies the cookie to the whole site
    ? got: /
    [?? assert] (a) HttpOnly puts the cookie out of reach of JavaScript
    ? got: #t
    [?? assert] (d) the cookie's lifetime matches #:token-validity-seconds
    ? got: 604800
    [?? assert] the redirect target is the dashboard
    ? got: /dashboard
    [?? assert] (b) Secure keeps it off plain HTTP
    ? got: #t
    [?? assert] the cookie is named as documented
    ? got: x-bewaking-session
    [?? assert] sign-in redirects, as the README's controller does
    ? got: 302
  [? test] the cookie lifetime can be aligned with the token's
    [?? assert] the envelope is sealed now
    ? got: #t
    [?? assert] the payload lifetime is separate from the cookie's
    ? got: #f
    [?? assert] the requested lifetime is recorded in the cookie
    ? got: 86400
  [? test] bad credentials get no cookie at all
    [?? assert] no session is created for a failed sign-in
    ? got: #f
    [?? assert] the failure is reported, not swallowed
    ? got: invalid credentials
    [?? assert] a wrong password is a plain 401
    ? got: 401
+----------------------------------------------+
[? suite] Web chapter: sealed objects as stateless state
  [? test] a cursor or half-finished form can be sealed the same way
    [?? assert] a sealed cursor round-trips
    ? got: page-3
    [?? assert] a client cannot page anywhere it was not sent
    ? got: #t
  [? test] the link answers only to the key that sealed it
    [?? assert] a link sealed elsewhere does not open here
    ? got: #f
  [? test] an edited link is worth nothing
    [?? assert] and garbage is not a link either
    ? got: #f
    [?? assert] the link was edited in the mail client
    ? got: #f
  [? test] a password-reset link round-trips with no table row
    [?? assert] the hour-long lifetime is recorded in the header
    ? got: #t
    [?? assert] the state comes back as an ordinary alist
    ? got: ((user . u-1) (action . reset-password))
    [?? assert] the user id is not readable in the link
    ? got: #f
    [?? assert] the link is a sealed envelope
    ? got: #t
  [? test] an expired link is refused by the server, not by the client
    [?? assert] before the expiry the link opens
    ? got: ((user . u-1) (action . reset-password))
    [?? assert] after the expiry the server refuses it
    ? got: #f
    [?? assert] and the header says so, for the log
    ? got: #t
+----------------------------------------------+
[? suite] Web chapter: auditing what is safe to log
  [? test] auditing garbage is #f, not an exception
    [?? assert] a malformed BWK3 value yields no metadata
    ? got: #f
    [?? assert] an unparseable cookie yields no metadata
    ? got: #f
    [?? assert] a missing cookie yields no metadata
    ? got: #f
  [? test] an expiry is reported as a time, and its absence as nothing
    [?? assert] a token sealed with a TTL records its expiry
    ? got: #t
    [?? assert] and the audit helper agrees it is live
    ? got: #f
    [?? assert] the audit reports no envelope expiry by default
    ? got: #f
  [? test] the envelope header is readable with no keys at all
    [?? assert] not the encryption key and not the signing key either
    ? got: #f
    [?? assert] the key id is reported, which is what rotation is keyed on
    ? got: default
    [?? assert] the audit output carries no key material
    ? got: #f
    [?? assert] the version is reported for the log
    ? got: BWK3
    [?? assert] a fresh session is not expired
    ? got: #f
    [?? assert] the creation time is reported
    ? got: #t
+----------------------------------------------+
[? suite] Web chapter: protecting a route
  [? test] the same session works as an API bearer token
    [?? assert] the granted permissions are what the token says
    ? got: (read-only access-files)
    [?? assert] the API route admits the header token
    ? got: 200
    [?? assert] the token identifies the caller without a database round-trip
    ? got: u-1
  [? test] a permission that was never granted is refused on the server
    [?? assert] the API route answers 401 rather than 403-by-omission
    ? got: 401
    [?? assert] the permission the user does have is enough
    ? got: #t
    [?? assert] a route needing nothing is open to a valid session
    ? got: #t
    [?? assert] the helper returns #f, not a partially authorized payload
    ? got: #f
    [?? assert] the browser route refuses a route the user may not use
    ? got: 302
  [? test] the payload is the identity, not the request
    [?? assert] the owner id comes from the sealed payload
    ? got: u-1
    [?? assert] a client-supplied user id is a hint, never the identity
    ? got: #f
  [? test] an expired session is refused, and sign-out clears the cookie
    [?? assert] and the helper returns #f for it
    ? got: #f
    [?? assert] sign-out deletes the cookie, the only cleanup there is
    ? got: 
    [?? assert] a token whose payload lifetime has passed is refused
    ? got: 302
    [?? assert] the deletion cookie expires immediately
    ? got: 0
    [?? assert] sign-out redirects to the login page
    ? got: 302
  [? test] the signed-in user is admitted
    [?? assert] permissions travel inside the token
    ? got: (read-only access-files)
    [?? assert] and its own payload expiry
    ? got: #t
    [?? assert] the browser route runs the handler
    ? got: 200
    [?? assert] the payload carries its own token id
    ? got: #t
    [?? assert] the handler sees the owner id from the payload
    ? got: u-1
    [?? assert] and 'name' came back as 'owner-name'
    ? got: Joe
    [?? assert] the thunk's 'email' came back as 'owner-email'
    ? got: joe@example.com
  [? test] every failure mode is a refusal, never an admission
    [?? assert] a keyring that cannot resolve the key id is refused
    ? got: 302
    [?? assert] arbitrary text is refused
    ? got: 302
    [?? assert] a second user's genuine session is admitted, as that user
    ? got: 200
    [?? assert] a cookie that is not a real envelope is refused
    ? got: 302
    [?? assert] an empty cookie is refused
    ? got: 302
    [?? assert] and it admits the *second* user, not the first
    ? got: u-2
    [?? assert] a tampered cookie is refused
    ? got: 302
    [?? assert] a request with no cookie is redirected to /login
    ? got: 302
+----------------------------------------------+
[? suite] Web chapter: keys, rotation and revocation
  [? test] rotation needs no downtime and no forced logout
    [?? assert] an old token still opens: nothing to migrate
    ? got: #t
    [?? assert] the key id is embedded in the envelope
    ? got: #t
    [?? assert] and so does a new one
    ? got: #t
    [?? assert] new logins are sealed with the current key
    ? got: #t
  [? test] retiring a key logs every session sealed with it out at once
    [?? assert] the retired key id stops opening sessions
    ? got: #f
    [?? assert] the current key keeps working
    ? got: #t
  [? test] keys stay secret and distinct, which is the whole requirement
    [?? assert] swapping the two keys does not open the session
    ? got: #f
    [?? assert] the encryption key does not appear in the token
    ? got: #f
    [?? assert] nor does the signing key
    ? got: #f
?? info - ran 5 tasks in: 0 seconds, 18601 microseconds

running unit tests from file: cli-spec.scm, entrypoint: spec


?? info - shuffled with seed 844052010 (replay with VERITAS_SEED=844052010)
+----------------------------------------------+
[? suite] CLI dispatch
  [? test] help and exit codes
    [?? assert] a token subcommand is required
    ? got: 1
    [?? assert] an unknown command exits with 1
    ? got: 1
    [?? assert] help documents the keyring option
    ? got: #t
    [?? assert] help documents the rotation metadata options
    ? got: #t
    [?? assert] help lists the token generate command
    ? got: #t
    [?? assert] help prints the usage banner
    ? got: #t
    [?? assert] version exits successfully
    ? got: 0
    [?? assert] help exits successfully
    ? got: 0
    [?? assert] help lists the token inspect command
    ? got: #t
    [?? assert] decrypting without keys fails
    ? got: 1
+----------------------------------------------+
[? suite] CLI object commands
  [? test] object expiry policy
    [?? assert] an object sealed with a past expiry is refused
    ? got: #t
  [? test] object round-trip
    [?? assert] object encrypt then decrypt round-trips a datum
    ? got: #t
+----------------------------------------------+
[? suite] CLI rotation metadata
  [? test] expiry is sealed into tokens and enforced
    [?? assert] --max-age-seconds accepts fresh data
    ? got: #t
    [?? assert] --allow-expired opens it anyway
    ? got: #t
    [?? assert] --ttl-seconds and --expires-at conflict
    ? got: #t
    [?? assert] an expired token exits with 1
    ? got: #t
  [? test] token inspect audits the header without keys
    [?? assert] inspect reports an expired envelope
    ? got: #t
    [?? assert] inspect rejects a non-envelope token
    ? got: #t
    [?? assert] inspect reports version, key id and expiry
    ? got: #t
+----------------------------------------------+
[? suite] CLI token commands
  [? test] key id and keyring rotation
    [?? assert] a keyring round-trips and rejects the wrong key
    ? got: #t
  [? test] wrong keys are rejected
    [?? assert] a wrong signing key exits with 1
    ? got: #t
  [? test] token round-trip
    [?? assert] generate then decrypt preserves the payload
    ? got: #t
+----------------------------------------------+
[? suite] CLI password commands
  [? test] password strength
    [?? assert] strength exits successfully
    ? got: 0
    [?? assert] a common password is reported weak
    ? got: #t
  [? test] password generate
    [?? assert] the requested length is honoured
    ? got: 32
    [?? assert] generation exits successfully
    ? got: 0
    [?? assert] symbols are excluded on request
    ? got: (lowercase uppercase digit)
+----------------------------------------------+
[? suite] CLI key derivation and dropped formats
  [? test] envelopes of dropped formats are refused
    [?? assert] a BWK2 token cannot be decrypted or inspected
    ? got: #t
    [?? assert] a BWK1 token cannot be decrypted or inspected
    ? got: #t
    [?? assert] an empty token is refused
    ? got: #t
  [? test] the key derivation is chosen when sealing and read back when opening
    [?? assert] a KDF parameter without --kdf is refused
    ? got: #t
    [?? assert] an Argon2id token round-trips through the CLI
    ? got: #t
  [? test] a refusal does not reveal which key ids the keyring configures
    [?? assert] an unknown key id and an edited body give the same message and exit code
    ? got: #t
  [? test] tampering and missing arguments are refused
    [?? assert] sealing an object without keys exits with 1
    ? got: #t
    [?? assert] generating without an owner id exits with 1
    ? got: #t
    [?? assert] an edited token exits with 1
    ? got: #t
?? info - ran 6 tasks in: 0 seconds, 10761 microseconds

running unit tests from file: password-spec.scm, entrypoint: spec


?? info - shuffled with seed 844052010 (replay with VERITAS_SEED=844052010)
+----------------------------------------------+
[? suite] Password character classes
  [? test] password-character-classes
    [?? assert] digits only
    ? got: (digit)
    [?? assert] an empty password has no classes
    ? got: ()
    [?? assert] uppercase letters only
    ? got: (uppercase)
    [?? assert] all four classes are detected
    ? got: (lowercase uppercase digit symbol)
    [?? assert] lowercase letters only
    ? got: (lowercase)
+----------------------------------------------+
[? suite] Password entropy
  [? test] password-entropy
    [?? assert] an empty password has zero entropy
    ? got: 0
    [?? assert] eight lowercase letters are ~37.6 bits
    ? got: #t
    [?? assert] adding a character class increases the entropy
    ? got: #t
+----------------------------------------------+
[? suite] Password strength
  [? test] password-strength
    [?? assert] sequential runs are flagged in the feedback
    ? got: #t
    [?? assert] common passwords get a specific warning
    ? got: #t
  [? test] strong-password?
    [?? assert] min-score lowers the bar
    ? got: #t
    [?? assert] a common word is not strong
    ? got: #f
    [?? assert] a long passphrase is strong
    ? got: #t
    [?? assert] a short mixed password is not strong
    ? got: #f
+----------------------------------------------+
[? suite] Password generation
  [? test] generate-strong-password
    [?? assert] too-short a request raises an error
    ? success catching error: misc-error: (#f ~A (generate-strong-password: length must be at least 4 to cover every character class.) #f)
    [?? assert] length is respected
    ? got: 32
    [?? assert] symbols can be excluded
    ? got: (lowercase uppercase digit)
    [?? assert] default generated passwords use every class
    ? got: (lowercase uppercase digit symbol)
?? info - ran 4 tasks in: 0 seconds, 5204 microseconds

finished running tests
;;; note: source file ./src/bewaking/bewaking.scm
;;;       newer than compiled /gnu/store/1xfphns7yvbizg1xwfnqigbnl3mrvfx7-profile/lib/guile/3.0/site-ccache/bewaking/bewaking.go
;;; found fresh local cache at /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/bewaking/trunk/src/bewaking/bewaking.scm.go
;;; note: source file ./src/bewaking/crypto.scm
;;;       newer than compiled /gnu/store/1xfphns7yvbizg1xwfnqigbnl3mrvfx7-profile/lib/guile/3.0/site-ccache/bewaking/crypto.go
;;; found fresh local cache at /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/bewaking/trunk/src/bewaking/crypto.scm.go
;;; note: source file ./src/bewaking/cli.scm
;;;       newer than compiled /gnu/store/1xfphns7yvbizg1xwfnqigbnl3mrvfx7-profile/lib/guile/3.0/site-ccache/bewaking/cli.go
;;; found fresh local cache at /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/bewaking/trunk/src/bewaking/cli.scm.go
;;; note: source file ./src/bewaking/password.scm
;;;       newer than compiled /gnu/store/1xfphns7yvbizg1xwfnqigbnl3mrvfx7-profile/lib/guile/3.0/site-ccache/bewaking/password.go
;;; found fresh local cache at /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/bewaking/trunk/src/bewaking/password.scm.go


--------------------------------------------------------------

Maak: the infinitely extensible command runner

Loading tasks from Maak file: /etc/byggsteg/job-clone/bewaking/trunk/maak.scm

Executing Maak tasks: test

--------------------------------------------------------------

=> Running Maak task: test

  Run project's tests.

→ running command: cd /etc/byggsteg/job-clone/bewaking/trunk && sudo maak deploy

API documentation saved to doc/api
index.texi: warning: must specify a title with a title command or @top
renamed './index' -> './doc/api-dist'
removed '/srv/http/jointhefreeworld.org/api-docs/bewaking/API.html'
removed '/srv/http/jointhefreeworld.org/api-docs/bewaking/bewaking_005fbewaking.html'
removed '/srv/http/jointhefreeworld.org/api-docs/bewaking/bewaking_005fcli.html'
removed '/srv/http/jointhefreeworld.org/api-docs/bewaking/bewaking_005fcrypto.html'
removed '/srv/http/jointhefreeworld.org/api-docs/bewaking/bewaking_005fpassword.html'
removed directory '/srv/http/jointhefreeworld.org/api-docs/bewaking'
mkdir: created directory '/srv/http/jointhefreeworld.org/api-docs/bewaking'
renamed 'doc/api-dist/API.html' -> '/srv/http/jointhefreeworld.org/api-docs/bewaking/API.html'
renamed 'doc/api-dist/bewaking_005fbewaking.html' -> '/srv/http/jointhefreeworld.org/api-docs/bewaking/bewaking_005fbewaking.html'
renamed 'doc/api-dist/bewaking_005fcli.html' -> '/srv/http/jointhefreeworld.org/api-docs/bewaking/bewaking_005fcli.html'
renamed 'doc/api-dist/bewaking_005fcrypto.html' -> '/srv/http/jointhefreeworld.org/api-docs/bewaking/bewaking_005fcrypto.html'
renamed 'doc/api-dist/bewaking_005fpassword.html' -> '/srv/http/jointhefreeworld.org/api-docs/bewaking/bewaking_005fpassword.html'
removed 'doc/api/index.texi'
removed directory 'doc/api'
removed directory 'doc/api-dist'
removed directory 'doc'


--------------------------------------------------------------

Maak: the infinitely extensible command runner

Loading tasks from Maak file: /etc/byggsteg/job-clone/bewaking/trunk/maak.scm

Executing Maak tasks: deploy

--------------------------------------------------------------

=> Running Maak task: deploy

  Generate documentation for the project and publish to web directory.