Skip to content

Adds new integration [wallenium/HA-menstrual-cycle] - #9845

Merged
frenck merged 4 commits into
hacs:masterfrom
wallenium:wallenium-add-integration
Oct 20, 2026
Merged

frenck merged 4 commits into
hacs:masterfrom
wallenium:wallenium-add-integration

Conversation

@wallenium

Copy link
Copy Markdown
Contributor

Checklist

  • I've read the publishing documentation.
  • I've added the HACS action to my repository.
  • (For integrations only) I've added the hassfest action to my repository.
  • The actions are passing without any disabled checks in my repository.
  • I've added a link to the action run on my repository below in the links section.
  • I've created a new release of the repository after the validation actions were run successfully.

Links

Link to current release: <Release 1.5.3>
Link to successful HACS action (without the ignore key): <HACS Action for 1.5.3>
Link to successful hassfest action (if integration): <Hassfest Action for 1.5.3>

@hacs-bot hacs-bot Bot changed the title Add 'wallenium/HA-menstrual-cycle' to integration list Adds new integration [wallenium/HA-menstrual-cycle] Aug 8, 2026
@hacs-bot

hacs-bot Bot commented Aug 8, 2026

Copy link
Copy Markdown

Thank you for submitting your repository to HACS (Home Assistant Community Store).

Your submission is in the review queue:
Your repository is waiting to be reviewed and included in HACS.

You can view the current queue here. Pull requests are processed in the order they were created, oldest first.

What to avoid during review:
To help reviewers work efficiently, don't do the following:

  • Comment on the pull request - The reviewer will contact you when they have feedback or questions.
  • Open a new pull request - This won't speed up the process and creates duplicate work.
  • Ask followers to comment on the pull request - This won't speed up the process and may delay your review.
  • Merge in the default branch - Only do this if a maintainer asks you to resolve a merge conflict.

If you need to make changes:
You can continue updating your repository while waiting for review. Changes to your repository will be reflected when the reviewer examines it. Only comment on the pull request if you need to withdraw your submission or have critical information for reviewers.

About draft pull requests:
Draft pull requests aren't included in the review queue. Your pull request may be marked as draft by a reviewer if issues need to be addressed. Once you've resolved all issues, mark it as ready for review to re-enter the queue.

What happens next:
Once a reviewer examines your submission, they'll either:

  • Approve and merge your pull request if everything meets the requirements
  • Request changes or ask questions if adjustments are needed

@hacs-bot

hacs-bot Bot commented Oct 17, 2026

Copy link
Copy Markdown

Thank you for submitting your repository to HACS (Home Assistant Community Store).

Your submission is in the review queue:
Your repository is waiting to be reviewed and included in HACS.

You can view the current queue here. Pull requests are processed in the order they were created, oldest first.

What to avoid during review:
To help reviewers work efficiently, don't do the following:

  • Comment on the pull request - The reviewer will contact you when they have feedback or questions.
  • Open a new pull request - This won't speed up the process and creates duplicate work.
  • Ask followers to comment on the pull request - This won't speed up the process and may delay your review.
  • Merge in the default branch - Only do this if a maintainer asks you to resolve a merge conflict.

If you need to make changes:
You can continue updating your repository while waiting for review. Changes to your repository will be reflected when the reviewer examines it. Only comment on the pull request if you need to withdraw your submission or have critical information for reviewers.

About draft pull requests:
Draft pull requests aren't included in the review queue. Your pull request may be marked as draft by a reviewer if issues need to be addressed. Once you've resolved all issues, mark it as ready for review to re-enter the queue.

What happens next:
Once a reviewer examines your submission, they'll either:

  • Approve and merge your pull request if everything meets the requirements
  • Request changes or ask questions if adjustments are needed

@frenck frenck left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Hi @wallenium, thanks for the submission! 👋

Two things need fixing before this can go in:

  1. The ICS feed URL, including its token, is published in state attributes. sensor.py (line 1440) puts ics_url: /menstruation_cycle/ics/<token>.ics into the main profile sensor's attributes, and at the default visibility level that attribute is always there. That means every Home Assistant user (including non-admins, and the sidebar panel is registered with require_admin=False) can read it, and the recorder writes it to the database on every state change. The feed itself is served by a raw route that bypasses Home Assistant authentication (__init__.py, lines 3880-3962), is enabled for every profile without the user asking for it, ignores the profile's visibility level (a profile switched to private keeps serving its period and fertility predictions to anyone with an old URL), and is not mentioned in the README. For data this sensitive, please:

    • stop exposing the URL in state attributes;
    • make the feed opt-in per profile (off by default) and respect the private visibility level;
    • only hand the URL to admins, for example by showing it in the options flow or returning it from an admin-only service or websocket command, which the dashboard panel can then use instead of reading the attribute;
    • document in the README that the feed works without a login, so anyone with the URL can read the predictions, and how to rotate it.
  2. Blocking I/O on the event loop. async_get_config_entry_diagnostics in diagnostics.py (line 54) calls _load_manifest_version(), which opens manifest.json synchronously (__init__.py, lines 230-237). Home Assistant flags that as a blocking call inside the event loop. You already have the value in the module-level RESOURCE_VERSION, so just use that. The same applies, on a smaller scale, to the Path.is_file() checks in the async HTTP handlers (__init__.py, lines 3810, 3832 and 3851) and in image.py (line 152, reached from async_update). Move those into the executor job that already reads the file, or drop them and handle FileNotFoundError from the read instead.

Not a blocker, just a suggestion: the dashboard panel loads Google Fonts at runtime (www/menstruation-cycle-dashboard-panel.js, line 6056), so every time someone opens a health-data panel, their browser contacts Google. Bundling the fonts or using the Home Assistant theme fonts would keep it fully local.

Once that's addressed, push a new release and re-request review.

../Frenck

                       

Blogging my personal ramblings at frenck.dev
Or subscribe to my free bi-weekly newsletter: frenck.dev/newsletter

@hacs-bot
hacs-bot Bot marked this pull request as draft October 18, 2026 19:59
@wallenium
wallenium marked this pull request as ready for review October 18, 2026 22:34
@wallenium

Copy link
Copy Markdown
Contributor Author

Hi @frenck
Thanks a lot for your review.
i made the requested changes. please review again

@frenck frenck left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Hi @wallenium, thanks for the quick turnaround on 1.9.0! 👋

One part of the ICS item from the last round is still open: there is no way to rotate the token when you need to.

_async_rotate_ics_token (__init__.py, lines 2507-2525) is only reachable from the stale-token repair flow (repairs.py, lines 1089-1117), and that issue only appears once the token is 365 days old (ICS_TOKEN_STALE_DAYS in const.py, line 554). Turning the feed off and on again does not create a new token either, so the old URL just starts working again. That causes two problems:

  • Someone who shared the URL and wants to revoke it can only switch the feed off for good. "Use the repair issue" (README, line 108) doesn't help for the first year.
  • On upgrade, async_setup_entry keeps the token that is already stored (__init__.py, lines 3292-3305). In 1.8.0 and earlier, that exact token was in the ics_url state attribute, readable by every user and written to the recorder. As soon as an admin turns the new opt-in feed on, that old URL is live again.

Please add an on-demand rotation (for example a "generate a new feed URL" checkbox in the options flow, or an admin-only service or websocket command the dashboard can call), and generate a fresh token when the feed is switched from off to on, so tokens from older releases never come back to life. Then update the README section on how to invalidate a URL.

Not a blocker, just a suggestion: the new menstruation_cycle_pill_taken, menstruation_cycle_lh_positive and menstruation_cycle_ovulation_confirmed events are fired (and shown in the logbook for every user) at the "Status only" visibility level too (__init__.py, lines 5339-5368, and _fire_ovulation_confirmed in sensor.py, lines 1505-1533). The options flow says "Status only" hides health details from others, so you may want to skip those events unless the level is "Full".

Once that's addressed, push a new release and re-request review.

../Frenck

                       

Blogging my personal ramblings at frenck.dev
Or subscribe to my free bi-weekly newsletter: frenck.dev/newsletter

@hacs-bot
hacs-bot Bot marked this pull request as draft October 19, 2026 03:08
wallenium added a commit to wallenium/HA-menstrual-cycle that referenced this pull request Oct 19, 2026
- **ICS feed token:** every time the feed is switched from off to on, a new token is created, so URLs from earlier versions (when the token was published as the `ics_url` attribute) or from an earlier period of use never work again. Administrators can also rotate the token at any time with the new "New feed URL" button next to the "Subscribe to calendar" link in the dashboard (admin-only websocket command `menstruation_cycle/rotate_ics_token`); the old URL stops working immediately. The README explains how to invalidate a URL.
- The events `menstruation_cycle_pill_taken`, `menstruation_cycle_lh_positive` and `menstruation_cycle_ovulation_confirmed` (and so their logbook entries) are only fired at visibility "Full" instead of "Full" and "Status only", because the logbook is readable by every user. Automations that rely on these events for a "Status only" profile need visibility "Full".

refer to hacs/default#9845 (review)
@wallenium

Copy link
Copy Markdown
Contributor Author

Hi @frenck
Thanks a lot for your input. I tried to harden the scripts with privacy in mind:

  • Services that change data or write files are now admin-only.
  • Read services respect the profile’s visibility level, so profiles set to “status only” or “private” no longer expose more than intended.
  • Sensor attributes follow the same visibility rules.
  • The ICS feed token is compared in constant time.
  • Exports are written owner-only (0600, no symlink following).
  • Health data no longer appears in the logs.

please check again if I fixed all regressions.

Simon

@wallenium
wallenium marked this pull request as ready for review October 19, 2026 22:36

@frenck frenck left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Hi @wallenium, thanks for the quick turnaround on 1.9.1 and the on-demand feed rotation! 👋

One small thing for a future release: two user-facing texts in strings.json and translations/*.json still describe the old behavior. The ics_feed_enabled option description still says to invalidate a shared URL through the repair issue or by turning the feed off, without the new "New feed URL" button, and the set_profile_visibility service description still says the read services are not affected by the visibility level, which 1.9.1 changed. Home Assistant shows these translations rather than services.yaml, so that is the text people read.

Approving and merging now.

../Frenck

                       

Blogging my personal ramblings at frenck.dev
Or subscribe to my free bi-weekly newsletter: frenck.dev/newsletter

@frenck
frenck merged commit e883812 into hacs:master Oct 20, 2026
13 checks passed
@hacs-bot

hacs-bot Bot commented Oct 20, 2026

Copy link
Copy Markdown

Congratulations! Your repository has been added to HACS 🎉

Your repository has been approved:
Your repository has been successfully merged into the HACS default repository list.
It might take up to 8 hours before your repository appears in HACS for users.

Resources:

Thank you for contributing to the Home Assistant community! 🎉

wallenium added a commit to wallenium/HA-menstrual-cycle that referenced this pull request Oct 20, 2026
- Two user-facing texts (`strings.json` and `translations/*.json`) still described the old behavior: the description of the option "Public ICS calendar feed" now mentions the dashboard button "New feed URL" for invalidating a shared URL, and the description of the service `set_profile_visibility` now says that below visibility "Full" the services that return a profile's data answer administrators only (as in `services.yaml`).

hacs/default#9845
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants