Groups keyboard shortcuts have been updated
Dismiss
See shortcuts

Intent to Ship: On-device Web Speech API

462 views
Skip to first unread message

Chromestatus

unread,
Jan 6, 2025, 8:10:51 PMJan 6
to blin...@chromium.org, ev...@google.com

Contact emails

ev...@google.com

Explainer

https://github.com/WebAudio/web-speech-api/pull/122

Specification

https://webaudio.github.io/web-speech-api

Summary

This feature adds on-device speech recognition support to the Web Speech API, allowing websites to ensure that neither audio nor transcribed speech are sent to a third-party service for processing. Websites can query the availability of on-device speech recognition for specific languages, prompt users to install the necessary resources for on-device speech recognition, and choose between on-device or cloud-based speech recognition as needed.



Blink component

Blink>Speech

Search tags

speech, recognition, local, offline, on-device

TAG review

None

TAG review status

Pending

Risks



Interoperability and Compatibility

None



Gecko: Positive Discussed at TPAC 2024 with representatives from Mozilla including Paul Adenot

WebKit: Positive Discussed at TPAC 2024 with representatives from Apple including Eric Carlson.

Web developers: Positive Commonly requested feature. Examples: https://webwewant.fyi/wants/55/ https://github.com/WebAudio/web-speech-api/issues/108 https://stackoverflow.com/questions/49473369/offline-speech-recognition-in-browser https://www.reddit.com/r/html5/comments/8jtv3u/offline_voice_recognition_without_the_webspeech/

Other signals:

WebView application risks

Does this intent deprecate or change behavior of existing APIs, such that it has potentially high risk for Android WebView-based applications?

None



Debuggability

None



Will this feature be supported on all six Blink platforms (Windows, Mac, Linux, ChromeOS, Android, and Android WebView)?

No

Initially supported on Windows, Mac, and Linux with ChromeOS support to follow.



Is this feature fully tested by web-platform-tests?

No

Flag name on about://flags

None

Finch feature name

InstallOnDeviceSpeechRecognition,OnDeviceWebSpeechAvailable,OnDeviceWebSpeech

Requires code in //chrome?

False

Estimated milestones

Shipping on desktop 135


Anticipated spec changes

Open questions about a feature may be a source of future web compat or interop issues. Please list open issues (e.g. links to known github issues in the project for the feature specification) whose resolution may introduce web compat/interop risk (e.g., changing to naming or structure of the API in a non-backward-compatible way).

https://github.com/WebAudio/web-speech-api/pull/122

Link to entry on the Chrome Platform Status

https://chromestatus.com/feature/6090916291674112?gate=4683906480340992

This intent message was generated by Chrome Platform Status.

Yoav Weiss (@Shopify)

unread,
Jan 7, 2025, 3:29:12 AMJan 7
to Chromestatus, blin...@chromium.org, ev...@google.com
On Tue, Jan 7, 2025 at 2:10 AM Chromestatus <ad...@cr-status.appspotmail.com> wrote:

Contact emails

ev...@google.com

Explainer

https://github.com/WebAudio/web-speech-api/pull/122

An actual explainer with usage examples would've been useful.
Also, the spec is not very detailed:
* It seems to be triggering resource downloads, but Fetch integration is not specified. 
* Are the resources downloaded partitioned per top-level site? What should typical download sizes be?



Specification

https://webaudio.github.io/web-speech-api

Summary

This feature adds on-device speech recognition support to the Web Speech API, allowing websites to ensure that neither audio nor transcribed speech are sent to a third-party service for processing. Websites can query the availability of on-device speech recognition for specific languages, prompt users to install the necessary resources for on-device speech recognition, and choose between on-device or cloud-based speech recognition as needed.



Blink component

Blink>Speech

Search tags

speech, recognition, local, offline, on-device

TAG review

None

TAG review status

Pending

Risks



Interoperability and Compatibility

None



Gecko: Positive Discussed at TPAC 2024 with representatives from Mozilla including Paul Adenot

WebKit: Positive Discussed at TPAC 2024 with representatives from Apple including Eric Carlson.

Links to the minutes would be helpful. Filing official positions would be even better.
 


Web developers: Positive Commonly requested feature. Examples: https://webwewant.fyi/wants/55/ https://github.com/WebAudio/web-speech-api/issues/108 https://stackoverflow.com/questions/49473369/offline-speech-recognition-in-browser https://www.reddit.com/r/html5/comments/8jtv3u/offline_voice_recognition_without_the_webspeech/

Other signals:

WebView application risks

Does this intent deprecate or change behavior of existing APIs, such that it has potentially high risk for Android WebView-based applications?

None



Debuggability

None



Will this feature be supported on all six Blink platforms (Windows, Mac, Linux, ChromeOS, Android, and Android WebView)?

No

Initially supported on Windows, Mac, and Linux with ChromeOS support to follow.



Is this feature fully tested by web-platform-tests?

No

Why not? Is it tested otherwise?  


Flag name on about://flags

None

Finch feature name

InstallOnDeviceSpeechRecognition,OnDeviceWebSpeechAvailable,OnDeviceWebSpeech

Requires code in //chrome?

False

Estimated milestones

Shipping on desktop 135


Anticipated spec changes

Open questions about a feature may be a source of future web compat or interop issues. Please list open issues (e.g. links to known github issues in the project for the feature specification) whose resolution may introduce web compat/interop risk (e.g., changing to naming or structure of the API in a non-backward-compatible way).

https://github.com/WebAudio/web-speech-api/pull/122

Link to entry on the Chrome Platform Status

https://chromestatus.com/feature/6090916291674112?gate=4683906480340992

This intent message was generated by Chrome Platform Status.

--
You received this message because you are subscribed to the Google Groups "blink-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+...@chromium.org.
To view this discussion visit https://groups.google.com/a/chromium.org/d/msgid/blink-dev/677c7f0e.2b0a0220.2e82a8.01f6.GAE%40google.com.

Daniel Clark

unread,
Jan 7, 2025, 1:34:29 PMJan 7
to Yoav Weiss (@Shopify), Chromestatus, blin...@chromium.org, ev...@google.com

Adding to Yoav’s feedback about the spec:

  • It’s implied that installOnDeviceSpeechRecognition() happens synchronously. Making this a blocking call seems problematic since it could involve a fetch and a download. I’d expect it to return a Promise (https://www.w3.org/TR/design-principles/#promises). And onDeviceWebSpeechAvailable should probably also be async since it could involve reading data from disk.
  • The SpeechRecognitionMode "ondevice-only" value is only defined by a comment in the IDL stating that it “Returns an error if on-device speech recognition is not available”. What specifically returns an error? SpeechRecognition.start() doesn’t return any value, and in other error conditions the behavior is to fire SpeechRecognitionErrorEvent. Also, what should the behavior be if SpeechRecognitionMode is changed after start() has already been called?

 

I also wonder if this should have a TAG review, especially given the privacy/fingerprinting implications of websites being able to query which on-device models are available.

 

-- Dan Clark

Evan Liu

unread,
Jan 7, 2025, 3:50:21 PMJan 7
to Daniel Clark, Yoav Weiss (@Shopify), Chromestatus, blin...@chromium.org
* Are the resources downloaded partitioned per top-level site? What should typical download sizes be?
This depends on the browser--for Chrome on Windows/Mac/Linux, there's only one instance of each on-device speech recognition language pack and each language pack is ~60MB. The spec doesn't necessarily dictate how the downloads are handled, only that websites should be allowed to trigger a download (or request a download) of a language. 

Links to the minutes would be helpful. Filing official positions would be even better.
I've filed official positions for Mozilla and WebKit

Why not? Is it tested otherwise?
Oops, I forgot to check that box. This feature is testable by web-platform-tests. 

It’s implied that installOnDeviceSpeechRecognition() happens synchronously. Making this a blocking call seems problematic since it could involve a fetch and a download. I’d expect it to return a Promise (https://www.w3.org/TR/design-principles/#promises). And onDeviceWebSpeechAvailable should probably also be async since it could involve reading data from disk.
Totally agree--the implementation of those two APIs on Chrome return promises. I'll make sure the spec reflects this.

The SpeechRecognitionMode "ondevice-only" value is only defined by a comment in the IDL stating that it “Returns an error if on-device speech recognition is not available”. What specifically returns an error? SpeechRecognition.start() doesn’t return any value, and in other error conditions the behavior is to fire SpeechRecognitionErrorEvent. Also, what should the behavior be if SpeechRecognitionMode is changed after start() has already been called?
Ah yeah, I'll update that comment to clarify that it fires a SpeechRecognitionErrorEvent. Updating the SpeechRecognitionMode after start() has been called has no effect on the existing session. This is consistent with how other SpeechRecognition attributes work (i.e. lang, maxAlternatives, etc.). This isn't explicitly stated anywhere in the spec, so I'll file a spec issue to clarify this as well.

As for mitigating privacy and fingerprinting risks, we've been collaborating with the team building the Translator API feature which also has the ability to download and detect language packs. Because the risks between these two features are nearly identical, on-device speech recognition language pack downloads will follow the same pattern and use the same permissions UI as on-device translation language packs. Here are some helpful links:
Privacy Design Doc

Thanks,
Evan
 

Yoav Weiss (@Shopify)

unread,
Jan 7, 2025, 10:20:12 PMJan 7
to Evan Liu, Domenic Denicola, Daniel Clark, Chromestatus, blin...@chromium.org
On Tue, Jan 7, 2025 at 9:50 PM Evan Liu <ev...@google.com> wrote:
* Are the resources downloaded partitioned per top-level site? What should typical download sizes be?
This depends on the browser--for Chrome on Windows/Mac/Linux, there's only one instance of each on-device speech recognition language pack and each language pack is ~60MB. The spec doesn't necessarily dictate how the downloads are handled, only that websites should be allowed to trigger a download (or request a download) of a language. 

This seems like it'd require at very least some extra considerations as part of the Privacy & Security section of the spec.
It would also be good to have that be explicitly an implementation-defined decision.

+Domenic Denicola who's been working on similar privacy models related to translations, and can potentially advise you on the best path there.


Links to the minutes would be helpful. Filing official positions would be even better.
I've filed official positions for Mozilla and WebKit

Why not? Is it tested otherwise?
Oops, I forgot to check that box. This feature is testable by web-platform-tests. 

It’s implied that installOnDeviceSpeechRecognition() happens synchronously. Making this a blocking call seems problematic since it could involve a fetch and a download. I’d expect it to return a Promise (https://www.w3.org/TR/design-principles/#promises). And onDeviceWebSpeechAvailable should probably also be async since it could involve reading data from disk.
Totally agree--the implementation of those two APIs on Chrome return promises. I'll make sure the spec reflects this.

The SpeechRecognitionMode "ondevice-only" value is only defined by a comment in the IDL stating that it “Returns an error if on-device speech recognition is not available”. What specifically returns an error? SpeechRecognition.start() doesn’t return any value, and in other error conditions the behavior is to fire SpeechRecognitionErrorEvent. Also, what should the behavior be if SpeechRecognitionMode is changed after start() has already been called?
Ah yeah, I'll update that comment to clarify that it fires a SpeechRecognitionErrorEvent. Updating the SpeechRecognitionMode after start() has been called has no effect on the existing session. This is consistent with how other SpeechRecognition attributes work (i.e. lang, maxAlternatives, etc.). This isn't explicitly stated anywhere in the spec, so I'll file a spec issue to clarify this as well.

As for mitigating privacy and fingerprinting risks, we've been collaborating with the team building the Translator API feature which also has the ability to download and detect language packs. Because the risks between these two features are nearly identical, on-device speech recognition language pack downloads will follow the same pattern and use the same permissions UI as on-device translation language packs. Here are some helpful links:
Privacy Design Doc

I don't think that's a link..

Rick Byers

unread,
Jan 8, 2025, 10:33:12 AMJan 8
to Yoav Weiss (@Shopify), Evan Liu, Domenic Denicola, Daniel Clark, Chromestatus, blin...@chromium.org
This is great to see! IMHO there are a bunch of great use-cases for on-device speech recognition which are likely not suitable for server-based approaches.

This is still only exposed via a legacy prefixed API, window.webkitSpeechRecognition, right?  Any reason why it wouldn't be trivial to unprefix the speech recognition API (supporting both prefixed and unprefixed) at the same time? In general we don't support making updates to APIs which are only exposed via non-standard legacy prefixed API names.

On Tue, Jan 7, 2025 at 10:20 PM Yoav Weiss (@Shopify) <yoav...@chromium.org> wrote:


On Tue, Jan 7, 2025 at 9:50 PM Evan Liu <ev...@google.com> wrote:
* Are the resources downloaded partitioned per top-level site? What should typical download sizes be?
This depends on the browser--for Chrome on Windows/Mac/Linux, there's only one instance of each on-device speech recognition language pack and each language pack is ~60MB. The spec doesn't necessarily dictate how the downloads are handled, only that websites should be allowed to trigger a download (or request a download) of a language. 

This seems like it'd require at very least some extra considerations as part of the Privacy & Security section of the spec.
It would also be good to have that be explicitly an implementation-defined decision.

+Domenic Denicola who's been working on similar privacy models related to translations, and can potentially advise you on the best path there.


Links to the minutes would be helpful. Filing official positions would be even better.
I've filed official positions for Mozilla and WebKit

Why not? Is it tested otherwise?
Oops, I forgot to check that box. This feature is testable by web-platform-tests. 

Have you written web platform tests for it? Have a link? 

Alex Russell

unread,
Jan 8, 2025, 11:25:18 AMJan 8
to blink-dev, Rick Byers, ev...@google.com, Domenic Denicola, dan...@microsoft.com, Chromestatus, blin...@chromium.org, Yoav Weiss
+1 to Dan's feedback; this needs an async API, likely with a streams design.

To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+unsubscribe@chromium.org.

--
You received this message because you are subscribed to the Google Groups "blink-dev" group.

To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+unsubscribe@chromium.org.

--
You received this message because you are subscribed to the Google Groups "blink-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+unsubscribe@chromium.org.

Mike Taylor

unread,
Jan 8, 2025, 11:31:24 AMJan 8
to Evan Liu, Daniel Clark, Yoav Weiss (@Shopify), Chromestatus, blin...@chromium.org

On 1/7/25 3:49 PM, 'Evan Liu' via blink-dev wrote:

As for mitigating privacy and fingerprinting risks, we've been collaborating with the team building the Translator API feature which also has the ability to download and detect language packs. Because the risks between these two features are nearly identical, on-device speech recognition language pack downloads will follow the same pattern and use the same permissions UI as on-device translation language packs. Here are some helpful links:
Privacy Design Doc

Should we update the Privacy considerations in the spec to describe these risks?

Jeffrey Yasskin

unread,
Jan 8, 2025, 11:35:12 AMJan 8
to Daniel Clark, Yoav Weiss (@Shopify), Chromestatus, blin...@chromium.org, ev...@google.com
On Tue, Jan 7, 2025 at 10:34 AM 'Daniel Clark' via blink-dev <blin...@chromium.org> wrote:

Adding to Yoav’s feedback about the spec:

  • It’s implied that installOnDeviceSpeechRecognition() happens synchronously. Making this a blocking call seems problematic since it could involve a fetch and a download. I’d expect it to return a Promise (https://www.w3.org/TR/design-principles/#promises). And onDeviceWebSpeechAvailable should probably also be async since it could involve reading data from disk.
  • The SpeechRecognitionMode "ondevice-only" value is only defined by a comment in the IDL stating that it “Returns an error if on-device speech recognition is not available”. What specifically returns an error? SpeechRecognition.start() doesn’t return any value, and in other error conditions the behavior is to fire SpeechRecognitionErrorEvent. Also, what should the behavior be if SpeechRecognitionMode is changed after start() has already been called?

 

I also wonder if this should have a TAG review, especially given the privacy/fingerprinting implications of websites being able to query which on-device models are available.


As a TAG member, I think a TAG review would probably result in useful feedback for this API. Please do send one.

Thanks,
Jeffrey
 

Evan Liu

unread,
Jan 9, 2025, 5:55:21 PMJan 9
to Jeffrey Yasskin, Daniel Clark, Yoav Weiss (@Shopify), Chromestatus, blin...@chromium.org
Have you written web platform tests for it? Have a link? 

Should we update the Privacy considerations in the spec to describe these risks?
That's a good idea! There's a section in the spec that requires user consent to download language packs to mitigate these risks, but I'll update this section to explicitly mention the fingerprinting risks.

this needs an async API, likely with a streams design.
The new methods added to the SpeechRecognition interface (onDeviceSpeechRecognitionAvailable and installOnDeviceSpeechRecognition) will return promises--I'll update the spec to reflect this. Regarding dropping the webkit prefix and replacing the non-prefixed version with a modern API design with promises, this probably wouldn't be feasible due to interoperability and backwards compatibility issues. While Firefox doesn't officially support the speech recognition section of the Web Speech API, it has a unprefixed implementation behind a flag and most of the guides on how to use the Web Speech API do something like window.SpeechRecognition || window.webkitSpeechRecognition; (Examples from developer.mozilla.orgcodeburst.iodev.to) and there are 17.8K instances of this kind of usage on Github alone. However, I think it's worth considering whether to create a new, modernized version of the API under a different name. I've filed a Github issue to continue this discussion with the Audio Working Group: https://github.com/WebAudio/web-speech-api/issues/130 

Privacy Design Doc
I don't think that's a link..
Oops sorry, here's the actual link: https://docs.google.com/document/d/12NHh8eVGmuqRuG9H4na4jGwCPD5UqIbC0bW_CJQi2Sc You'll probably have to request access to view the doc.

I also wonder if this should have a TAG review, especially given the privacy/fingerprinting implications of websites being able to query which on-device models are available.
As a TAG member, I think a TAG review would probably result in useful feedback for this API. Please do send one.
I've sent a TAG design review request for this here: https://github.com/w3ctag/design-reviews/issues/1038

Thanks for all of the input so far!
Evan


Rick Byers

unread,
Jan 15, 2025, 10:59:23 AMJan 15
to Evan Liu, Jeffrey Yasskin, Daniel Clark, Yoav Weiss (@Shopify), Chromestatus, blin...@chromium.org
Thank you Evan. Given the samples and github hits you've shared, I agree that web compat will constrain us from making breaking changes to the APi when we unprefix. That's a shame, but is a known reason why we long ago gave up on prefixes as a safe way to do experimental API development. So are you OK with adding unprefixing to this intent (or if you prefer, a new one that this is blocked on)? IMHO the webkit-prefixed entrypoint can just be an alias, but we should UseCounter it independently - with all the examples you've shared I'm hoping maybe we can even delete the prefixed API name relatively easily? But we should keep that as separate future work. 

The TAG or others may argue that we should block on-device support on modernizing the API elsewhere (eg. exposing under a brand new name, or adding duplicate methods for the promise versions), but personally I think that goes too far so I won't withhold my personal LGTM on such an argument. Other API owners may feel differently. 

It's great to see Mozilla officially positive on this. There's no TAG or WebKit feedback yet, but let's keep our ears open. From my perspective this is currently only blocked on unprefixing and landing the spec updates you mentioned. 

Rick Byers

unread,
Jan 15, 2025, 1:49:00 PMJan 15
to Evan Liu, Jeffrey Yasskin, Daniel Clark, Yoav Weiss (@Shopify), Chromestatus, blin...@chromium.org
One more question, it looks like the latest spec has not been published to the gh-pages branch yet. Can you please make sure that your changes are visible here

API owners (chrishtr, bratell, yoavweiss, vmpstr and me) met and agreed:
  • It would be helpful if you wrote a short explainer.
    • The spec PR (while a pretty easy way to see what APIs you're adding) doesn't really make for a good explainer because it doesn't really explain the context and "why" for people who don't have any knowledge of the web speech API. TAG may not look at your review without a high-level explainer. 
  • Making window.SpeechRecognition an alias of window.webkitSpeechRecognition is OK with us
    • This means the two new methods will be available both via webkitSpeechRecognition and SpeechRecognition. Adding new methods to prefixed APIs isn't ideal, but we agreed that it's not worth the extra work to separate these especially given the documentation you shared using 'const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;'
    • But we do want a UseCounter specific to webkitSpeechRecognition so we get a good idea when it can be removed (should be trivial with LegacyWindowAlias_Measure)
  • We are looking for the spec and WPTs to match the implementation before approving
  • The group agrees that discussions of modernizing the API are non-blocking for this intent
Thanks,
   Rick

Evan Liu

unread,
Jan 21, 2025, 7:33:30 PMJan 21
to Stmh, Rick Byers, Jeffrey Yasskin, Daniel Clark, Yoav Weiss (@Shopify), Chromestatus, blink-dev
 So are you OK with adding unprefixing to this intent (or if you prefer, a new one that this is blocked on)?
Yeah, I think that's a great idea! I'm also in favor of tracking usage of the prefixed version with the goal of possibly dropping it entirely in the future.

It would be helpful if you wrote a short explainer.
 I've sent out a PR adding an explainer for on-device speech recognition: https://github.com/WebAudio/web-speech-api/pull/133

We are looking for the spec and WPTs to match the implementation before approving
I've sent out a PR updating the spec to match the WPTs, which return Promises that resolve to booleans for the two new methods: https://github.com/WebAudio/web-speech-api/pull/132

One more question, it looks like the latest spec has not been published to the gh-pages branch yet. Can you please make sure that your changes are visible here
Dominique Hazael-Massieux is currently working on this--the change should be auto-published once this PR is merged: https://github.com/WebAudio/web-speech-api/pull/129

Thanks for the feedback and please let me know if anyone has any additional comments or concerns!

On Wed, Jan 15, 2025 at 10:55 AM Stmh <hateds...@gmail.com> wrote:
It would be nice to speak with someone privately, as I may be able to add some additional insight. 

Rick Byers

unread,
Jan 22, 2025, 11:25:51 AMJan 22
to Evan Liu, Stmh, Jeffrey Yasskin, Daniel Clark, Yoav Weiss (@Shopify), Chromestatus, blink-dev
On Tue, Jan 21, 2025 at 7:33 PM Evan Liu <ev...@google.com> wrote:
 So are you OK with adding unprefixing to this intent (or if you prefer, a new one that this is blocked on)?
Yeah, I think that's a great idea! I'm also in favor of tracking usage of the prefixed version with the goal of possibly dropping it entirely in the future.

Great, thank you!  

It would be helpful if you wrote a short explainer.
 I've sent out a PR adding an explainer for on-device speech recognition: https://github.com/WebAudio/web-speech-api/pull/133

The explainer looks great, thanks!

We are looking for the spec and WPTs to match the implementation before approving
I've sent out a PR updating the spec to match the WPTs, which return Promises that resolve to booleans for the two new methods: https://github.com/WebAudio/web-speech-api/pull/132

Perfect, please follow up here once the PR lands (or gets blocked for some reason outside your control, including lack of review).

One more question, it looks like the latest spec has not been published to the gh-pages branch yet. Can you please make sure that your changes are visible here
Dominique Hazael-Massieux is currently working on this--the change should be auto-published once this PR is merged: https://github.com/WebAudio/web-speech-api/pull/129

Thanks!

Paul Adenot

unread,
Feb 6, 2025, 5:13:50 AM (9 days ago) Feb 6
to blink-dev, rby...@chromium.org, hateds...@gmail.com, jyas...@chromium.org, dan...@microsoft.com, yoav...@chromium.org, Chromestatus, blink-dev, ev...@google.com
All,

Answering with both hats separately here: Mozilla developer implementing this, and chair of the CG in which this is happening (and of the WG that will adopt this when it's rechartering time).

While we (Mozilla) are extremely happy to see work in the area, are participating in the standard, and are currently implementing, and can be clearly counted as "Positive" (putting my standard author hat on) this is **nowhere near ready** for exposure on the web, as clearly outlined by a few people in this thread. Lots of questions remain, PRs are in flights, the small amount of test is using APIs that haven't been agreed upon nor merged. Progress is being made every day, but not agreement has been reached. It has only been a few months since Evan's announcement of this at TPAC, we can spend more time getting this ready. We barely have an explainer, that is already outdated and hasn't been reviewed by all the implementors.

I have called for a special, mostly dedicated, meeting to be able to expedite lots of the items required for shipping something like this last Thursday, and I'm waiting for an answer from Apple on this, as they are actively commenting on the current text, and it wouldn't be appropriate to not have them on board here. In the meantime, we're making progress on a day-to-day basis. Should it be needed, we can also set up regular meeting with a higher frequency, as it has been done before when there was a strong need to drive a spec to a shippable state quickly.

All that to say, shipping this in Chrome 135, that enters Beta in about a month, feels premature.

Best,
Paul.
Reply all
Reply to author
Forward
0 new messages