Skip to content

Latest commit

 

History

History
263 lines (188 loc) · 8.44 KB

File metadata and controls

263 lines (188 loc) · 8.44 KB

Priority Task: XID Document Public Distribution Workflow

Problem Statement

There is no workflow in bc-envelope-cli to convert a XID document with private keys and provenance mark generator into a publicly distributable version while preserving signatures.

To create a publicly distributable XID document, users need to:

  1. Elide or omit private keys - Replace private key assertions with ELIDED placeholders (preserving digest tree) or remove them entirely
  2. Elide the provenance mark generator - The generator allows creating new provenance marks and should be elided (not omitted) to preserve the digest tree
  3. Preserve the signature - If signed, the signature should remain valid after elision
  4. OR re-sign - If modifications break the signature, the document needs re-signing

Current Gaps

1. Commands Missing --private and --generator Output Options

These commands hard-code PrivateOptions::Include and don't support controlling output:

Command Missing Options
xid method add --private, --generator
xid method remove --private, --generator
xid delegate add --private, --generator
xid delegate update --private, --generator
xid delegate remove --private, --generator
xid service add --private, --generator
xid service update --private, --generator
xid service remove --private, --generator
xid attachment add --private, --generator
xid attachment remove --private, --generator
xid provenance next --private, --generator

2. Key Commands Missing --generator Option

These commands have --private but not --generator:

Command Missing Options
xid key add --generator
xid key update --generator
xid key remove --generator

3. --generator elide Rejected at Runtime

The GeneratorOptions::Elide variant exists and is listed in help text, but is explicitly rejected at runtime in xid new with:

"Elide is not allowed for 'xid new'. Use 'omit' (the default)..."

This is correct for xid new (can't elide what doesn't exist), but elide should be available for commands that operate on existing documents.

4. No Standalone Export Command

No command exists to simply re-output an existing XID document with different private/generator options without modifying it.


Implementation Plan

Phase 1: Create Shared Output Options Infrastructure (DRY Refactor)

Goal: Create reusable argument structs that can be composed into commands needing output control.

1.1 Create OutputOptions struct in src/cmd/xid/mod.rs or new file output_options.rs

/// Options controlling how sensitive data is output in XID documents.
#[derive(Debug, Args, Default)]
pub struct OutputOptions {
    #[command(flatten)]
    pub private_opts: PrivateOutputArgs,

    #[command(flatten)]
    pub generator_opts: GeneratorOutputArgs,
}

#[derive(Debug, Args, Default)]
pub struct PrivateOutputArgs {
    /// Whether to include, omit, elide, or encrypt private keys.
    #[arg(long = "private", default_value = "include")]
    pub private: PrivateOptions,
}

#[derive(Debug, Args, Default)]
pub struct GeneratorOutputArgs {
    /// Whether to include, omit, elide, or encrypt the provenance mark generator.
    #[arg(long = "generator", default_value = "include")]
    pub generator: GeneratorOptions,
}

1.2 Update xid_document_to_ur_string signature

Update to accept OutputOptions instead of individual PrivateOptions and Option<GeneratorOptions>:

pub fn xid_document_to_ur_string(
    xid_document: &XIDDocument,
    output_opts: &OutputOptions,
    password_args: Option<&WritePasswordArgs>,
    shared_password: Option<String>,
    signing_options: XIDSigningOptions,
) -> Result<String>

1.3 Create trait for commands with output options

pub trait HasOutputOptions {
    fn output_options(&self) -> &OutputOptions;
}

Phase 2: Add Output Options to Key Commands

Goal: Add --generator option to existing key commands.

2.1 Update xid key add

  • Add GeneratorOutputArgs to CommandArgs
  • Pass generator option to xid_document_to_ur_string

2.2 Update xid key update

  • Add GeneratorOutputArgs to CommandArgs
  • Pass generator option to xid_document_to_ur_string

2.3 Update xid key remove

  • Add GeneratorOutputArgs to CommandArgs
  • Pass generator option to xid_document_to_ur_string

Phase 3: Add Output Options to Non-Key Commands

Goal: Add both --private and --generator options to all XID-modifying commands.

3.1 Method commands

  • xid method add - Add OutputOptions
  • xid method remove - Add OutputOptions

3.2 Delegate commands

  • xid delegate add - Add OutputOptions
  • xid delegate update - Add OutputOptions
  • xid delegate remove - Add OutputOptions

3.3 Service commands

  • xid service add - Add OutputOptions
  • xid service update - Add OutputOptions
  • xid service remove - Add OutputOptions

3.4 Attachment commands

  • xid attachment add - Add OutputOptions
  • xid attachment remove - Add OutputOptions

3.5 Provenance commands

  • xid provenance next - Add OutputOptions

Phase 4: Add xid export Subcommand

Goal: Create a command to re-output an existing XID document with different output options without modifying it.

4.1 Create src/cmd/xid/export.rs

/// Export a XID document with specified output options.
///
/// This command reads an existing XID document and outputs it with
/// the specified handling of private keys and provenance generator.
/// Use this to create publicly distributable versions of XID documents.
#[derive(Debug, Args)]
#[group(skip)]
pub struct CommandArgs {
    #[command(flatten)]
    output_opts: OutputOptions,

    #[command(flatten)]
    password_args: ReadWritePasswordArgs,

    #[command(flatten)]
    verify_args: VerifyArgs,

    #[command(flatten)]
    signing_args: SigningArgs,

    #[command(flatten)]
    envelope_args: EnvelopeArgs,
}

4.2 Register in src/cmd/xid/mod.rs

Add Export(export::CommandArgs) to SubCommands enum.

4.3 Example usage in documentation

# Create publicly distributable version (elide secrets, preserve signature)
envelope xid export --private elide --generator elide $FULL_XID

# Create minimal version (omit secrets, re-sign required)
envelope xid export --private omit --generator omit --sign inception $FULL_XID

# Encrypt secrets for storage, re-sign
envelope xid export --private encrypt --generator encrypt \
    --encrypt-password "secret" --sign inception $FULL_XID

Phase 5: Update Tests

5.1 Add tests for new functionality in tests/test_xid.rs

  • Test --private elide preserves signature
  • Test --generator elide preserves signature
  • Test --private omit requires re-signing
  • Test --generator omit requires re-signing
  • Test all combinations work correctly

5.2 Add tests for xid export in tests/test_xid_export.rs

  • Test export with elision preserves signature
  • Test export with omission invalidates signature
  • Test export with encryption
  • Test round-trip: create → export public → verify signature

Phase 6: Update Documentation

6.1 Update docs/XID.md

  • Add section on creating publicly distributable XID documents
  • Document xid export command
  • Add workflow examples for common use cases

6.2 Add inline help text

Ensure all new options have clear /// doc comments that appear in --help.


Implementation Order

  1. Phase 1 - DRY infrastructure (blocks all other phases)
  2. Phase 2 - Key commands (small scope, validates Phase 1 design)
  3. Phase 3 - Non-key commands (apply pattern from Phase 2)
  4. Phase 4 - Export command (uses all infrastructure from prior phases)
  5. Phase 5 - Tests (validates all functionality)
  6. Phase 6 - Documentation (documents completed features)

Success Criteria

  • All XID-modifying commands support --private and --generator options
  • xid export command exists and works correctly
  • Elision preserves existing signatures
  • Omission correctly requires re-signing
  • No code duplication for output option handling
  • Tests cover all new functionality
  • Documentation is complete and accurate