Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
# TODO: add os: [ubuntu-latest, macos-latest, windows-latest]
os: [macos-latest, ubuntu-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
Expand Down
26 changes: 13 additions & 13 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ exclude = [
]

[workspace.package]
version = "0.0.1-rc.5"
version = "0.0.1-rc.1"
license = "Apache-2.0"
rust-version = "1.93"

Expand All @@ -35,15 +35,15 @@ thiserror = "2"
uuid = { version = "1", features = ["v4"] }
git2 = "0.20.4"

auths-core = { path = "crates/auths-core", version = "0.0.1-rc.5" }
auths-id = { path = "crates/auths-id", version = "0.0.1-rc.5" }
auths-verifier = { path = "crates/auths-verifier", version = "0.0.1-rc.5", default-features = false }
auths-policy = { path = "crates/auths-policy", version = "0.0.1-rc.5" }
auths-index = { path = "crates/auths-index", version = "0.0.1-rc.5" }
auths-telemetry = { path = "crates/auths-telemetry", version = "0.0.1-rc.5" }
auths-crypto = { path = "crates/auths-crypto", version = "0.0.1-rc.5", default-features = false }
auths-sdk = { path = "crates/auths-sdk", version = "0.0.1-rc.5" }
auths-test-utils = { path = "crates/auths-test-utils", version = "0.0.1-rc.5" }
auths-infra-git = { path = "crates/auths-infra-git", version = "0.0.1-rc.5" }
auths-infra-http = { path = "crates/auths-infra-http", version = "0.0.1-rc.5" }
auths-storage = { path = "crates/auths-storage", version = "0.0.1-rc.5" }
auths-core = { path = "crates/auths-core", version = "0.0.1-rc.1" }
auths-id = { path = "crates/auths-id", version = "0.0.1-rc.1" }
auths-verifier = { path = "crates/auths-verifier", version = "0.0.1-rc.1", default-features = false }
auths-policy = { path = "crates/auths-policy", version = "0.0.1-rc.1" }
auths-index = { path = "crates/auths-index", version = "0.0.1-rc.1" }
auths-telemetry = { path = "crates/auths-telemetry", version = "0.0.1-rc.1" }
auths-crypto = { path = "crates/auths-crypto", version = "0.0.1-rc.1", default-features = false }
auths-sdk = { path = "crates/auths-sdk", version = "0.0.1-rc.1" }
auths-test-utils = { path = "crates/auths-test-utils", version = "0.0.1-rc.1" }
auths-infra-git = { path = "crates/auths-infra-git", version = "0.0.1-rc.1" }
auths-infra-http = { path = "crates/auths-infra-http", version = "0.0.1-rc.1" }
auths-storage = { path = "crates/auths-storage", version = "0.0.1-rc.1" }
8 changes: 4 additions & 4 deletions crates/auths-core/src/trust/pinned.rs
Original file line number Diff line number Diff line change
Expand Up @@ -480,9 +480,12 @@ mod tests {

let dir = tempfile::tempdir().unwrap();
let path = dir.path().join("known_identities.json");

// Seed the store file so concurrent threads don't race on first-create
std::fs::write(&path, "[]").unwrap();

let store = Arc::new(PinnedIdentityStore::new(path));

// Spawn multiple threads that all try to pin different identities
let handles: Vec<_> = (0..10)
.map(|i| {
let store = Arc::clone(&store);
Expand All @@ -494,16 +497,13 @@ mod tests {
})
.collect();

// Wait for all threads
for handle in handles {
handle.join().unwrap();
}

// Verify all pins are present and file is not corrupted
let all = store.list().unwrap();
assert_eq!(all.len(), 10);

// Verify each pin exists
for i in 0..10 {
let did = format!("did:keri:E{:03}", i);
assert!(
Expand Down
26 changes: 15 additions & 11 deletions crates/auths-id/src/storage/registry/hooks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
//! repository that touch a `.stale` sentinel file. This triggers cache
//! invalidation on the next read operation.

#[cfg(not(windows))]
use std::fs;
#[cfg(unix)]
use std::os::unix::fs::PermissionsExt;
Expand All @@ -22,15 +23,19 @@ pub enum HookError {
}

/// Hook types that invalidate the cache.
#[cfg(not(windows))]
const CACHE_HOOKS: &[&str] = &["post-merge", "post-checkout", "post-rewrite"];

/// Marker comment to identify the linearity enforcement hook.
#[cfg(not(windows))]
const LINEARITY_MARKER: &str = "# auths-linearity-enforcement";

/// Marker comment to identify our hooks.
#[cfg(not(windows))]
const HOOK_MARKER: &str = "# auths-cache-invalidation";

/// The shell script snippet that touches the sentinel file.
#[cfg(not(windows))]
fn cache_invalidation_snippet(cache_dir: &Path) -> String {
let sentinel = cache_dir.join(".stale");
format!(
Expand All @@ -51,24 +56,22 @@ touch "{}" 2>/dev/null || true
/// # Arguments
/// * `repo_path` - Path to the Git repository (e.g., `~/.auths`)
/// * `cache_dir` - Path to the cache directory (e.g., `~/.auths/.cache`)
pub fn install_cache_hooks(repo_path: &Path, cache_dir: &Path) -> Result<(), HookError> {
// Skip on Windows - hooks are optional for cache functionality
pub fn install_cache_hooks(_repo_path: &Path, _cache_dir: &Path) -> Result<(), HookError> {
#[cfg(windows)]
{
return Ok(());
}

#[cfg(not(windows))]
{
let git_dir = find_git_dir(repo_path)?;
let git_dir = find_git_dir(_repo_path)?;
let hooks_dir = git_dir.join("hooks");

// Create hooks directory if it doesn't exist
if !hooks_dir.exists() {
fs::create_dir_all(&hooks_dir)?;
}

let snippet = cache_invalidation_snippet(cache_dir);
let snippet = cache_invalidation_snippet(_cache_dir);

for hook_name in CACHE_HOOKS {
install_hook(&hooks_dir, hook_name, &snippet)?;
Expand Down Expand Up @@ -149,15 +152,15 @@ fn find_git_dir(repo_path: &Path) -> Result<std::path::PathBuf, HookError> {
/// Uninstall cache invalidation hooks from a Git repository.
///
/// Removes our snippet from hooks but preserves other user content.
pub fn uninstall_cache_hooks(repo_path: &Path) -> Result<(), HookError> {
pub fn uninstall_cache_hooks(_repo_path: &Path) -> Result<(), HookError> {
#[cfg(windows)]
{
return Ok(());
}

#[cfg(not(windows))]
{
let git_dir = find_git_dir(repo_path)?;
let git_dir = find_git_dir(_repo_path)?;
let hooks_dir = git_dir.join("hooks");

for hook_name in CACHE_HOOKS {
Expand Down Expand Up @@ -208,6 +211,7 @@ pub fn uninstall_cache_hooks(repo_path: &Path) -> Result<(), HookError> {

/// The pre-receive hook script that rejects non-fast-forward pushes and ref
/// deletions for Auths identity ref namespaces.
#[cfg(not(windows))]
const LINEARITY_HOOK_SCRIPT: &str = r#"#!/bin/sh
# auths-linearity-enforcement
# Reject non-fast-forward pushes and ref deletions for Auths identity refs.
Expand Down Expand Up @@ -263,15 +267,15 @@ exit 0
///
/// # Arguments
/// * `repo_path` - Path to the Git repository (e.g., `~/.auths`)
pub fn install_linearity_hook(repo_path: &Path) -> Result<(), HookError> {
pub fn install_linearity_hook(_repo_path: &Path) -> Result<(), HookError> {
#[cfg(windows)]
{
return Ok(());
}

#[cfg(not(windows))]
{
let git_dir = find_git_dir(repo_path)?;
let git_dir = find_git_dir(_repo_path)?;
let hooks_dir = git_dir.join("hooks");

if !hooks_dir.exists() {
Expand Down Expand Up @@ -320,15 +324,15 @@ pub fn install_linearity_hook(repo_path: &Path) -> Result<(), HookError> {
///
/// Removes the auths linearity section from the pre-receive hook while
/// preserving any other content.
pub fn uninstall_linearity_hook(repo_path: &Path) -> Result<(), HookError> {
pub fn uninstall_linearity_hook(_repo_path: &Path) -> Result<(), HookError> {
#[cfg(windows)]
{
return Ok(());
}

#[cfg(not(windows))]
{
let git_dir = find_git_dir(repo_path)?;
let git_dir = find_git_dir(_repo_path)?;
let hook_path = git_dir.join("hooks").join("pre-receive");

if !hook_path.exists() {
Expand Down
74 changes: 74 additions & 0 deletions docs/plans/v1_launch.md
Original file line number Diff line number Diff line change
Expand Up @@ -425,3 +425,77 @@ parallelized across 2-3 engineers. The WASM crypto stub (0.1) and FFI tests
(0.4, 0.5) are the most time-sensitive since they gate the embedding story.
The API surface cleanup (0.2, 0.3) is the most semver-sensitive since public
API changes after 0.1.0 require a minor version bump.


---

## Launch workflow

Step 1: Login
```
cargo login
```

# Paste your crates.io API token

Step 2: Dry run first

Run this to catch packaging issues before publishing anything:

```bash
for crate in auths-crypto auths-policy auths-telemetry auths-index \
auths-verifier auths-core auths-infra-http auths-id \
auths-storage auths-sdk auths-infra-git auths-cli auths; do
echo "=== $crate ==="
cargo publish --dry-run -p "$crate" 2>&1 | tail -3
echo
done
```

Step 3: Publish in dependency order

Each cargo publish needs the previous crate to be indexed (takes ~30s-1min), so add a sleep between them:

# Tier 0: No workspace dependencies
cargo publish -p auths-crypto
cargo publish -p auths-policy
cargo publish -p auths-telemetry
cargo publish -p auths-index
sleep 60

# Tier 1: Depends on Tier 0
cargo publish -p auths-verifier # depends on auths-crypto
sleep 60

# Tier 2: Depends on Tier 0-1
cargo publish -p auths-core # depends on auths-crypto, auths-verifier
cargo publish -p auths-infra-http # depends on auths-core, auths-verifier
sleep 60

# Tier 3: Depends on Tier 0-2
cargo publish -p auths-id # depends on core, crypto, policy, verifier, index
cargo publish -p auths-sdk # depends on core, id, policy, crypto, verifier
cargo publish -p auths-storage # depends on core, id, verifier, index
sleep 60

# Tier 4: Depends on Tier 0-3
cargo publish -p auths-infra-git # depends on core, sdk, verifier
sleep 60

# Tier 5: Depends on everything
cargo publish -p auths-cli
sleep 30

# Wrapper crate (currently empty deps, publish whenever)
cargo publish -p auths

Important notes

- Version bump first — you'll want to update the workspace version in Cargo.toml from 0.0.1-rc.5 to 0.1.0 before
publishing. Every version.workspace = true crate picks it up automatically, but the [workspace.dependencies] version
strings also need updating.
- You can't overwrite — once a version is published to crates.io, it's permanent. If something goes wrong mid-publish, bump
to 0.1.1 for the remaining crates.
- The sleeps are conservative — crates.io indexing usually takes 30-60 seconds. If a publish fails with "can't find
dependency", just wait and retry.
- auths-test-utils and xtask are publish = false and will be skipped automatically.