Skip to content

Add/remove/replace/info commands added to wbn-sign CLI#913

Merged
rferens merged 1 commit intoWICG:mainfrom
rferens:new_commands
Mar 31, 2026
Merged

Add/remove/replace/info commands added to wbn-sign CLI#913
rferens merged 1 commit intoWICG:mainfrom
rferens:new_commands

Conversation

@rferens
Copy link
Copy Markdown
Collaborator

@rferens rferens commented Mar 17, 2026

Summary
This change refactors the core signing logic into a new high-level SignedWebBundle API, introduces support for multiple signatures

Key Changes

  • New SignedWebBundle API: Introduced a central class in src/core/signed-web-bundle.ts that provides a simplified, high-level interface for creating, loading, and modifying signed web bundles. It supports:

    • Signing an unsigned bundle with one or more strategies.
    • Adding or removing signatures from an existing signed bundle.
    • Retrieving the Web Bundle ID (App ID).
    • Loading signed bundles directly from bytes.
  • Enhanced Integrity Block Management:

    • Moved IntegrityBlock to a dedicated core module and added the ability to parse existing integrity blocks from CBOR.
    • Refactored IntegrityBlockSigner to be internal, deprecating several methods in favor of the new SignedWebBundle and utility functions.
  • Infrastructure & Utilities:

    • Added new utility functions for identifying pure vs. signed bundles and verifying signatures.
    • Updated tsconfig.json to strip internal declarations from the generated types.

@rferens rferens marked this pull request as draft March 17, 2026 18:31
@zgroza zgroza self-requested a review March 19, 2026 11:22
@rferens rferens force-pushed the new_commands branch 5 times, most recently from 39100e9 to a126c8c Compare March 19, 2026 17:32
@rferens rferens marked this pull request as ready for review March 19, 2026 17:32
Comment thread js/sign/src/core/integrity-block.ts Outdated
Comment thread js/sign/src/signers/integrity-block-signer.ts Outdated
Comment thread js/sign/src/signers/integrity-block-signer.ts Outdated
Comment thread js/sign/src/core/integrity-block.ts
Comment thread js/sign/src/core/signed-web-bundle.ts
Comment thread js/sign/src/core/signed-web-bundle.ts
Comment on lines +67 to +68
/** @internal */
async signInternal(): Promise<IntegrityBlock> {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

So, essentially this whole class, including the normal .sign() is @internal, isn't it? (I mean, if the constructor is...)

I'd argue that this class should provide a clear interface to the callers: you create it using whatever arguments and then call sign(). But here we have SignedWebBundle calling .signInternal() (which looks like it should only be used from inside this class (and probably should be marked private)), why?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I'd like to have this class internal, but for backward compatiblity(BC) it cannot be at least now (however I think about making it @deprecated now and @internal some day later, when almost no one uses old API.)

Regarding SignedWebBundle using .signInternal - yeah, I though 'internal' for package-internal, not class-internal, but perhaps its just my mistake. as the convention is probably what you suggested. I just created signInternal to be used by SignedWebBundle, which do not do not necessary step like forming Cbor or concatenating to create singeWebBundle.
Again, BC make things harder - the sign method should just return a new integrity block, but because of BC cannot. What do you think about deprecating sign (to change output format one day, when its internal) and renaming this method returning IntegrityBlock (that should be named 'sign')) sth like ' signAndGetIntegrityBlock()'

Comment thread js/sign/src/signers/integrity-block-signer.ts Outdated
return new Uint8Array(buffer);
}

/** @deprecated Very general function; moved to utils */
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Why then leave this here? The whole class has been removed from exports, so removing things from here instead of deprecating will not break anything (more).

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

The class was not removed from exports. It's kept for backward compatibilty. @deprecated is not a perfect tool for what I want to achieve, but good enough. I want to :
-use some methods still internally
-discourage users from using it externally, but

  • do not break their current code, but introduce unpleasant warnings

Comment thread js/sign/src/wbn-sign.ts
@rferens rferens mentioned this pull request Mar 21, 2026
Copy link
Copy Markdown
Collaborator

@zgroza zgroza left a comment

Choose a reason for hiding this comment

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

This looks good overall, just PTAL at a few last comments.

this.pureWebBundle,
this.integrityBlock,
[signingStrategy]
).signAndGetIntegrityBlock();
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I am not really a fan of re-signing every time a new signature is added. Can You sign lazily only when the actual bytes are requested?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

We do not resign anything with the same key - creating a signer and signing is still mostly 'additive' and requires mostly O(m) (m-number of new signatures). The only redundant operations, the same every time, are: calculating hash, and formatting stripped IngerityBlock as CBOR and validating it. I believe improving thet to be computed once should be sufficient , is it?

Having SignedWebBundle in the 'lazy state' that does not include new signetures may involve some difficulties and introduce some error-proneness for further implementations. For example when sb. first add singature and later removes same - it would require special implementation for such cases.

I propose then sth else. When Signer finally is depracated we can move out calculating web_bundle hash and cache getting stripped cbor in IntegrityBlock to be calculcated once if not change. WDYT? Would it be ok?

Comment thread js/sign/src/signers/integrity-block-signer.ts Outdated
Comment thread js/sign/src/signers/integrity-block-signer.ts Outdated
this.signingStrategies = signingStrategies;
}

/** @deprecated This class is only internal, use SignedWebBundle instead. Sign() is going to change interface in next releases. */
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Nit: Line length consistency doesn't look in line with the above. Can you verify that everything here passes the same prettier checks?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I think it's how prettier works - It's not maximal length, but just suggested and it sometimes misses long lines. See: this

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I'll make sure that those comments are well line-broken anyway.

this.signingStrategies = signingStrategies;
}

/** @deprecated This class is only internal, use SignedWebBundle instead. Sign() is going to change interface in next releases. */
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I'm not sure if it's necessary to put those notices on every method if they're already on the constructor.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Okay, I'll replace it with the shorter comment you suggested below: /** @deprecated This class will become only internal in a future release, use SignedWebBundle instead*/

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

However I'll leave a comment next to @deprecated to explain it anyway

}

// TODO: Move this method to SignedWebBundle/WebBundle class, signer do not need this, especially externally
/** @deprecated This class is only internal, use SignedWebBundle instead*/
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Like above: it's not internal yet

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Yeah, I meant it to be internal for external users but still allowed to used, so marked with @deprecated. But maybe it's not clear enough. Changed.

Comment thread js/sign/src/wbn-sign.ts
Comment thread js/sign/README.md
Comment thread js/sign/src/utils/utils.ts Outdated
Comment thread js/sign/src/utils/utils.ts
Apply suggestions from code review

Co-authored-by: Zgroza (Luke) Klimek <zgroza@google.com>
@rferens rferens merged commit 19a856d into WICG:main Mar 31, 2026
10 checks passed
rferens added a commit that referenced this pull request Apr 2, 2026
This PR expands the CLI with new commands for managing integrity blocks.

CLI Improvements:
Updated the wbn-sign CLI with a new command-based interface (sign, add-signature, remove-signature, replace-signature, and info), see README for more info.
Added colored console output for better readability using the colors package.
This is a continuation of #913, which was split into API(original PR) and CLI(this PR) parts.
---------

Co-authored-by: Zgroza (Luke) Klimek <zgroza@google.com>
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.

2 participants