Skip to content

Conversation

@ChrisPenner
Copy link
Member

@ChrisPenner ChrisPenner commented Nov 14, 2025

Overview

Adds a migration which hashes and signs all of a codebase's history comments, as a step towards syncing them with Share.

Implementation approach and notes

Adds a Migration which:

  • Creates a Personal Key for the user.
    • A personal key is a randomly generated EdDSA public/private key pair which is stored in the user's credentials.json file.
    • This key can be used to assert the user's identity across code-servers in a cryptographically verifiable way.
  • Maps over all the user's history comments and hashes and signs them, we'll need the hash and author for syncing with share.
  • Extracts the credentials management into its own package, since we need to use it in the migration and can't depend on unison-cli there.
  • ensure hashing uses a canonicalized serialization of the components to ensure no hash-collisions that can result froma simple concatenation

Interesting/controversial decisions

It's hard to know whether personal keys are overkill or not, while it would likely be possible to get away with just Share auth in the short term, I don't think it's really sound in the presence of multiple codeservers; I opted to implement personal keys because I believe I'll get mileage out of them in the future, e.g. they can be used for things like service-account auth in CI and such.

Test coverage

  • Verify that the credentials.json is ported correctly.

I tested the migration by creating some comments on a trunk build and running the migration on it, then creating some new comments.

Loose ends

Next up is to implement the comment sync APIs.

@aryairani
Copy link
Contributor

We need a passphrase option here, right? Or what's the standard

@ChrisPenner
Copy link
Member Author

@aryairani

We need a passphrase option here, right? Or what's the standard

Hrmm, this is a deep rabbit hole to go down that adds a ton of work;

  • Do we support various keychains?
  • Yubikeys/physical devices?
  • Various password managers?
  • gpg agent?

I was planning on having ucm manage these complete for the user as basic EdDSA keys, rather than having the user configure their own keys; thus it's basically treated the same as your Share token, but with the added ability of cryptographic signing and a public key.

Do you think passphrases or the other mentioned features are table-stakes?

@ChrisPenner ChrisPenner force-pushed the cp/change-comments-sync branch 2 times, most recently from 37b15a0 to aa40862 Compare November 18, 2025 00:09
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Part of the migration, this adds nullable versions of the new columns.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Part 3 of the migration, this makes the new columns non-nullable in SQLite's own annoying way, which is creating a new table and copying all the data between them, then dropping the original and renaming the new one.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This just moved due to import needs.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some changes here to support the new comment hashes, author thumbprints, and author signatures.

Copy link
Member Author

@ChrisPenner ChrisPenner Nov 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that migrations need a credential manager I rewrote the bulk of the credential manager stuff to support a proper singleton, which should be safer when multiple parts of the app may have their own credential managers; I also pulled it out into its own package so it can be accessed in the Migration.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All new Personal Key stuff.

A personal key is just a public-private EdDsa key pair, which is stored in the user's credentials.json file.

@ChrisPenner ChrisPenner force-pushed the cp/change-comments-sync branch from 28e1af1 to 0af09bd Compare December 19, 2025 16:18
@ChrisPenner ChrisPenner force-pushed the cp/change-comments-sync branch from 0af09bd to de952d7 Compare January 5, 2026 21:20
@ChrisPenner ChrisPenner force-pushed the cp/change-comments-sync branch from 258064e to 6f4d4ac Compare January 6, 2026 18:40
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved into the unison-credentials package

- http-types
- ki
- lens
- lock-file
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved into unison-credentials

@ChrisPenner ChrisPenner force-pushed the cp/change-comments-sync branch from abdb970 to 9b4a76e Compare January 7, 2026 00:08
@ChrisPenner ChrisPenner marked this pull request as ready for review January 7, 2026 00:09
@ChrisPenner ChrisPenner requested a review from aryairani January 7, 2026 00:12
@aryairani
Copy link
Contributor

aryairani commented Jan 7, 2026

it's basically treated the same as your Share token, but with the added ability of cryptographic signing and a public key.

Okay, makes sense. Sorry I just spotted your reply now.

Edit: It was a draft PR at the time so I feel less bad about not noticing the comment.

@aryairani
Copy link
Contributor

Hrmm, this is a deep rabbit hole to go down that adds a ton of work;

  • Do we support various keychains?
  • Yubikeys/physical devices?
  • Various password managers?
  • gpg agent?

Which approach does command-line ssh use?

cabal-version: 1.12

-- This file has been generated from package.yaml by hpack version 0.36.0.
-- This file has been generated from package.yaml by hpack version 0.38.1.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

danger here; in the other cabal files too

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

side note: stack 3.1.1 (which I haven't tested yet?) has a force-hpack option (or something) which will make this less dangerous once we're on that version.

Copy link
Contributor

@aryairani aryairani left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

after reverting the cabal hpack version lines (sorry) I would say it can be merged

@ChrisPenner
Copy link
Member Author

ChrisPenner commented Jan 8, 2026

@aryairani

Hrmm, this is a deep rabbit hole to go down that adds a ton of work;

  • Do we support various keychains?
  • Yubikeys/physical devices?
  • Various password managers?
  • gpg agent?

Which approach does command-line ssh use?

ssh does support encrypted keys of course, in SSH's case that key represents your ability to sign into remote servers,
in our case, currently the key is only used to signify the author of a comment.

If we're legitimately concerned about a user's credentials file being stolen or leaked then we shouldn't be storing unencrypted auth tokens on disk at all; since currently an attacker would just take the user's OAuth token rather than their personal key.

AFAIK storing unencrypted credentials is quite a common practice, e.g. the AWS cli just stores your unencrypted creds at ~/.aws/credentials; google does the same in ~/.config/gcloud/

Not saying it's bad to allow requiring a password for this stuff, and maybe if we end up using the personal key for accessing Unison Cloud we may wish to add more layers of security, but at the moment I don't think it's worth the time to implement, since if an attacker has access to your file-system we have bigger concerns than them fraudulently signing comments in your name;

Hrmm, Is that a reasonable stance?

@aryairani
Copy link
Contributor

Makes sense.
🤞 for CI

@github-actions
Copy link

github-actions bot commented Jan 8, 2026

Some tests with 'continue-on-error: true' have failed:

  • Cabal / smoke-test

Created by continue-on-error-comment

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.

3 participants