Skip to content

[PM-38329] policies stop converting policy data on every response - #8204

Merged
JaredScar merged 11 commits into
mainfrom
ac/pm-38329-policies-stop-converting-policy-data-on-every-response
Aug 24, 2026
Merged

[PM-38329] policies stop converting policy data on every response#8204
JaredScar merged 11 commits into
mainfrom
ac/pm-38329-policies-stop-converting-policy-data-on-every-response

Conversation

@JaredScar

Copy link
Copy Markdown
Contributor

🎟️ Tracking

https://bitwarden.atlassian.net/browse/PM-38329

📔 Objective

Stops converting the policy data on every response for policies

…JsonConverter for Data property, enhancing null safety and JSON handling. Introduce RawJsonConverter utility for efficient raw JSON serialization/deserialization. Update related namespaces and remove unnecessary deserialization logic.
…ertions, improving JSON handling and readability. Introduce new tests for PolicyResponseModel and PolicyStatusResponseModel to ensure consistent serialization with legacy implementations. Add RawJsonConverterTests to validate raw JSON serialization/deserialization behavior.
@JaredScar
JaredScar requested a review from a team as a code owner August 13, 2026 16:34
@JaredScar JaredScar added the ai-review Request a Claude code review label Aug 13, 2026
@JaredScar
JaredScar requested a review from eliykat August 13, 2026 16:34
@JaredScar JaredScar added the t:bugfix Change Type - Bugfix label Aug 13, 2026
@github-actions

github-actions Bot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

🤖 Bitwarden Claude Code Review

Overall Assessment: APPROVE

Reviewed the switch of Policy.Data from a Dictionary<string, object> round trip to raw JSON pass-through across the internal, status, and public API response models, plus the new RawJsonConverter and RawJsonSchemaFilter. Traced the wire format for each model against the previous behavior: data-less policies still emit "data": null for PolicyResponseModel (both internal and public) and "data": {} for PolicyStatusResponseModel, and populated policies emit the stored object unchanged since no DictionaryKeyPolicy was applied previously. Confirmed the new string Data shadowing in the public model resolves cleanly under System.Text.Json property-hierarchy rules, that the schema filter mirrors the existing EncryptedStringSchemaFilter pattern, and that all writes to Policy.Data flow through PolicyDataValidator.ValidateAndSerialize, so Utf8JsonWriter.WriteRawValue receives valid, already-escaped JSON.

Code Review Details

No findings. The two open threads already have author responses explaining the intentional null vs {} difference between the Vault-facing and Admin Console-facing models; no additional concerns to add.

Comment thread src/Api/AdminConsole/Public/Models/Response/PolicyResponseModel.cs Outdated
Comment thread src/Core/Utilities/RawJsonConverter.cs
Comment thread src/Api/AdminConsole/Models/Response/Organizations/PolicyStatusResponseModel.cs Outdated
@JaredScar JaredScar added t:tech-debt Change Type - Tech debt and removed t:bugfix Change Type - Bugfix labels Aug 13, 2026
…policies with no stored data by serializing as "{}" instead of null. Update PolicyResponseModel to allow setting Data property. Introduce RawJsonSchemaFilter to adjust OpenAPI schema generation for properties using RawJsonConverter. Add tests for PolicyStatusResponseModel and RawJsonSchemaFilter to ensure correct serialization and schema behavior.
Comment thread src/SharedWeb/Swagger/RawJsonSchemaFilter.cs Outdated
@codecov

codecov Bot commented Aug 13, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 90.00000% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 63.31%. Comparing base (7f38699) to head (eca4d21).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
src/SharedWeb/Swagger/RawJsonSchemaFilter.cs 84.61% 2 Missing and 2 partials ⚠️

❗ There is a different number of reports uploaded between BASE (7f38699) and HEAD (eca4d21). Click for more details.

HEAD has 1 upload less than BASE
Flag BASE (7f38699) HEAD (eca4d21)
2 1
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #8204      +/-   ##
==========================================
- Coverage   68.57%   63.31%   -5.27%     
==========================================
  Files        2401     2403       +2     
  Lines      104043   104069      +26     
  Branches     9426     9432       +6     
==========================================
- Hits        71349    65888    -5461     
- Misses      30341    35926    +5585     
+ Partials     2353     2255      -98     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

…PI generation. Enhance tests to verify correct schema behavior for properties with and without nullability. This ensures accurate representation of JSON types in generated schemas.
@eliykat
eliykat requested review from r-tome and removed request for eliykat August 14, 2026 23:12
@eliykat

eliykat commented Aug 14, 2026

Copy link
Copy Markdown
Member

@r-tome I'm OOO shortly, can you please do this review given you created the ticket? Thanks!

Comment thread src/Api/AdminConsole/Models/Response/Organizations/PolicyStatusResponseModel.cs Outdated
@r-tome
r-tome requested a review from jrmccannon August 19, 2026 15:23

@r-tome r-tome left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This looks good to me but I designed the solution so I tagged @jrmccannon to review it.

I feel like the comments/xmldoc are too Claude-y. Maybe retry using simplified technical english.

Comment thread src/Api/AdminConsole/Public/Models/Response/PolicyResponseModel.cs
Comment thread src/SharedWeb/Swagger/RawJsonSchemaFilter.cs Outdated
Comment thread test/Api.Test/AdminConsole/Models/Response/PolicyResponseModelTests.cs Outdated
Comment thread test/Api.Test/AdminConsole/Models/Response/PolicyResponseModelTests.cs Outdated
Comment thread test/Api.Test/AdminConsole/Models/Response/PolicyResponseModelTests.cs Outdated
Comment thread test/Api.Test/AdminConsole/Public/Models/Response/PolicyResponseModelTests.cs Outdated
Comment thread test/Core.Test/Utilities/RawJsonConverterTests.cs Outdated
Comment thread test/Core.Test/Utilities/RawJsonConverterTests.cs Outdated
Comment thread test/Core.Test/Utilities/RawJsonConverterTests.cs Outdated
…ved serialization

- Refactored PolicyStatusResponseModel and PolicyResponseModel to ensure consistent serialization behavior, preserving legacy wire format for policies with no stored data.
- Updated unit tests to reflect changes in serialization logic, replacing legacy models with dictionary-based deserialization for accurate JSON output comparison.
- Removed obsolete RawJsonConverterTests as they are no longer needed with the updated serialization approach.
@JaredScar
JaredScar requested a review from jrmccannon August 19, 2026 17:29
Comment thread src/Api/AdminConsole/Models/Response/Organizations/PolicyStatusResponseModel.cs Outdated
Comment thread src/Core/Utilities/RawJsonConverter.cs Outdated
Comment thread src/SharedWeb/Swagger/RawJsonSchemaFilter.cs Outdated
@JaredScar
JaredScar requested a review from jrmccannon August 20, 2026 15:52
…JSON object for missing data

- Modified PolicyStatusResponseModel to return an empty JSON object instead of null when no data is stored, ensuring compatibility with policy-specific initialization logic.
- Updated comments for clarity regarding serialization behavior.
- Adjusted RawJsonConverter and RawJsonSchemaFilter documentation for improved understanding of JSON handling.
Comment thread test/Migrator.Test/packages.lock.json Outdated
},
"Stripe.net": {
"type": "Transitive",
"resolved": "48.5.0",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is this supposed to be here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Accident! Good catch!

Comment thread test/Migrator.Test/packages.lock.json
@JaredScar
JaredScar requested a review from jrmccannon August 20, 2026 16:17
…le projects

- Upgraded various Microsoft.AspNetCore and Microsoft.Extensions packages to version 10.0.10 in the lock files for Commercial.Core, Commercial.Infrastructure.EntityFramework, Scim, Services.Pam, Sso, and test projects.
- Ensured consistent dependency resolution and improved compatibility with the latest features and fixes in the updated packages.
Comment thread src/Api/AdminConsole/Models/Response/Organizations/PolicyResponseModel.cs Outdated

@jrmccannon jrmccannon left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This is the opposite of what I meant.

JaredScar and others added 2 commits August 20, 2026 17:33
…property

- Changed the Data property in PolicyResponseModel from private to public set, enabling modification of the property after object instantiation.
- This adjustment enhances flexibility in handling policy data within the response model.
@JaredScar
JaredScar requested a review from jrmccannon August 20, 2026 21:34

@jrmccannon jrmccannon left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks for all the clean up. One more thing would be to do a manual test of exporting the API spec to do one final gut check to make sure it outputs the spec correctly. These are used for the sdk api bindings so we should validate that to make sure things are breaking across projects.

@JaredScar
JaredScar merged commit a12937c into main Aug 24, 2026
45 checks passed
@JaredScar
JaredScar deleted the ac/pm-38329-policies-stop-converting-policy-data-on-every-response branch August 24, 2026 17:26
cyprain-okeke added a commit that referenced this pull request Aug 25, 2026
QA round 3: rendering org names verbatim let mail clients linkify
names that look like domains (e.g. "40167.Client.Org" became a link to
http://40167.client.org/ in the provider payment method email). Insert
a zero-width non-joiner after each "." and "@" via the new
CoreHelpers.PreventEmailAutoLinking so the visible text is unchanged
but the token no longer matches a domain. Handlebars encodes the
character as &#8204; in HTML parts; the text templates now use
triple-stache for the name fields so the raw character (not the
entity) lands in the plain-text part, matching the PM-42262 approach
for text-part links.
cyprain-okeke added a commit that referenced this pull request Aug 27, 2026
* [PM-40167] feat: Update billing domain email copy

Refreshes subject lines and body copy for nine billing emails
(license, seat limits, provider payment method, and Families for
Enterprise sponsorship) per the PM-38898 terminology epic. Copy
ships in-place with no feature flag per product decision.

Also removes the unused offerAcceptanceDate parameter from
SendFamiliesForEnterpriseRemoveSponsorshipsEmailAsync, sanitizes
the sponsor org name in offer emails, and fixes the sponsorship
reverting text template referencing a nonexistent {{Date}} property.

* [PM-42261] fix: Address QA defects on billing domain emails

- PM-42261: render organization names verbatim in the seat limit,
  Secrets Manager limit, and sponsorship offer email bodies instead of
  applying [dot]/[at] substitution, matching the subject line
- PM-42262: point the provider payment method email at the
  billing/payment-details route, update the help article anchor, and
  render plain text links as bare URLs instead of HTML anchors or
  HTML-encoded ampersands
- PM-42264: inherit BaseMailModel so the Secrets Manager machine
  accounts limit email footer renders the copyright year

Also aligns sponsorship offer email test expectations with the
PM-41951 copy that shipped on main and won the merge conflict.

* [PM-42261] fix: Render organization names verbatim in remaining billing emails

QA round 2 found the same [dot] substitution in two more emails changed
by PM-40167: the Families sponsorship removal email and the self-host
license expired email. Render the organization name verbatim in both,
matching the earlier fix, and do the same for the provider payment
method email which had the identical latent issue. Handlebars {{ }}
interpolation still HTML-encodes the values.

* [PM-42261] fix: Stop mail clients auto-linking dotted organization names

QA round 3: rendering org names verbatim let mail clients linkify
names that look like domains (e.g. "40167.Client.Org" became a link to
http://40167.client.org/ in the provider payment method email). Insert
a zero-width non-joiner after each "." and "@" via the new
CoreHelpers.PreventEmailAutoLinking so the visible text is unchanged
but the token no longer matches a domain. Handlebars encodes the
character as &#8204; in HTML parts; the text templates now use
triple-stache for the name fields so the raw character (not the
entity) lands in the plain-text part, matching the PM-42262 approach
for text-part links.

* Fix lint whitespace and restore SanitizeForEmail doc placement

The PreventEmailAutoLinking helper was inserted between SanitizeForEmail
and its XML summary, leaving the new method with two summaries and
SanitizeForEmail undocumented. Reorder so each method keeps its own
docs, and fix the missing indentation on the new CoreHelpers test.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai-review Request a Claude code review t:tech-debt Change Type - Tech debt

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants