From cc296f9e9910f4500fa0064646e85061109722f8 Mon Sep 17 00:00:00 2001 From: feruzm Date: Wed, 5 Aug 2026 05:48:37 +0000 Subject: [PATCH 1/2] Self-hosted: say the Hivesigner client id is filled in for hosted blogs The registration job writes the shared ecency.app client id for every active tenant, but the Configuration Editor still told the owner to register an app themselves or email us and then type the id in. That describes work a managed tenant will never do, and reads as a broken login until they do it. Rewrites the client id and login methods descriptions to state the hosted case first, keep the self-hosted route, and say an owner's own id is never overwritten, which the reconcile already guarantees but nothing told them. Locks it with a test asserting the hosted case is described as automatic, so the editor and the job cannot drift apart again the way they just did. --- .../floating-menu/config-fields.test.ts | 19 +++++++++++++++++++ .../features/floating-menu/config-fields.ts | 4 ++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/apps/self-hosted/src/features/floating-menu/config-fields.test.ts b/apps/self-hosted/src/features/floating-menu/config-fields.test.ts index e2e748be7c..4b322a421e 100644 --- a/apps/self-hosted/src/features/floating-menu/config-fields.test.ts +++ b/apps/self-hosted/src/features/floating-menu/config-fields.test.ts @@ -64,6 +64,25 @@ describe('hivesigner client id', () => { expect(description).toContain('ecency.app'); }); + /** + * A managed tenant's client id is written by the registration job, not by the + * owner, so copy telling them to set it themselves describes work they will + * never do and a login they will believe is broken until they do it. + * + * Asserted on the field an owner actually reads rather than on the job, because + * the job being right is what makes this text wrong: the two drifted apart once + * already, with the editor promising a manual step the reconcile had removed. + */ + it('says the hosted case is automatic, and that an own id survives it', () => { + const description = fieldAt(CLIENT_ID_PATH)?.description ?? ''; + + expect(description).toMatch(/hosted by Ecency/i); + expect(description).toMatch(/filled in for you|automatically/i); + // The reconcile leaves a non-shared value alone; the owner has to be told so, + // or setting their own app reads as a change something else may undo. + expect(description).toMatch(/never overwritten|not be overwritten/i); + }); + it('is pointed at from the login methods field', () => { expect(fieldAt(METHODS_PATH)?.description).toContain('Hivesigner'); }); diff --git a/apps/self-hosted/src/features/floating-menu/config-fields.ts b/apps/self-hosted/src/features/floating-menu/config-fields.ts index 025020f3b6..02c377ecd9 100644 --- a/apps/self-hosted/src/features/floating-menu/config-fields.ts +++ b/apps/self-hosted/src/features/floating-menu/config-fields.ts @@ -356,7 +356,7 @@ export const configFieldsMap: Record = { type: 'array', allowedValues: AUTH_METHODS, description: - 'Available login methods: keychain, hivesigner, hiveauth. Hivesigner also needs a client id, set under General Settings > Hivesigner.', + 'Available login methods: keychain, hivesigner, hiveauth. Hivesigner also needs a client id under General Settings > Hivesigner, which blogs hosted by Ecency are given automatically.', }, }, }, @@ -455,7 +455,7 @@ export const configFieldsMap: Record = { // when cleared, and null erases the stored section on merge. type: 'string', description: - "Hivesigner login stays hidden until this is set. Either register your own Hivesigner app and put its id here, or email hello@ecency.com to get this site's /auth address registered on the shared ecency.app app, then put ecency.app here.", + "Hivesigner login stays hidden until this is set. On a blog hosted by Ecency the shared ecency.app app is filled in for you, once this site's /auth address has been registered on chain, so there is normally nothing to do here. To use a different app, register your own and put its id here; it is never overwritten. On a self-hosted instance, register your own app or email hello@ecency.com.", }, }, }, From a6435e3014290f21039c114a5afcf6c060e423c0 Mon Sep 17 00:00:00 2001 From: feruzm Date: Wed, 5 Aug 2026 06:42:34 +0000 Subject: [PATCH 2/2] Self-hosted: keep the ecency.app save step for self-hosters The rewrite dropped it. Nothing writes this field on a self-hosted instance: the reconcile iterates the hosting database, so an owner who emails us and waits sees the login stay hidden for a step that was never going to happen by itself. Restores the instruction on the self-hosted branch of the description, and adds a test for it. The existing case asserted the three substrings were present, and they all were in the revision that had dropped the step, so it caught nothing. --- .../floating-menu/config-fields.test.ts | 17 +++++++++++++++++ .../src/features/floating-menu/config-fields.ts | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/apps/self-hosted/src/features/floating-menu/config-fields.test.ts b/apps/self-hosted/src/features/floating-menu/config-fields.test.ts index 4b322a421e..9f221a45d1 100644 --- a/apps/self-hosted/src/features/floating-menu/config-fields.test.ts +++ b/apps/self-hosted/src/features/floating-menu/config-fields.test.ts @@ -83,6 +83,23 @@ describe('hivesigner client id', () => { expect(description).toMatch(/never overwritten|not be overwritten/i); }); + /** + * The email route is only half an instruction. Nothing writes the field on a + * self-hosted instance: the reconcile iterates the hosting database, so an + * owner who emails us and waits sees the button stay hidden for a step that + * was never going to happen on its own. + * + * `gives both routes to a working setup` does not cover this. It asserts the + * three substrings are present, and they all were in a revision that had + * dropped the save step, which is how this shipped for review. + */ + it('tells a self-hoster taking the email route to save ecency.app themselves', () => { + const description = fieldAt(CLIENT_ID_PATH)?.description ?? ''; + + expect(description).toMatch(/self-hosted/i); + expect(description).toMatch(/put ecency\.app here/i); + }); + it('is pointed at from the login methods field', () => { expect(fieldAt(METHODS_PATH)?.description).toContain('Hivesigner'); }); diff --git a/apps/self-hosted/src/features/floating-menu/config-fields.ts b/apps/self-hosted/src/features/floating-menu/config-fields.ts index 02c377ecd9..3d9d5f13d7 100644 --- a/apps/self-hosted/src/features/floating-menu/config-fields.ts +++ b/apps/self-hosted/src/features/floating-menu/config-fields.ts @@ -455,7 +455,7 @@ export const configFieldsMap: Record = { // when cleared, and null erases the stored section on merge. type: 'string', description: - "Hivesigner login stays hidden until this is set. On a blog hosted by Ecency the shared ecency.app app is filled in for you, once this site's /auth address has been registered on chain, so there is normally nothing to do here. To use a different app, register your own and put its id here; it is never overwritten. On a self-hosted instance, register your own app or email hello@ecency.com.", + "Hivesigner login stays hidden until this is set. On a blog hosted by Ecency the shared ecency.app app is filled in for you, once this site's /auth address has been registered on chain, so there is normally nothing to do here. To use a different app instead, register your own and put its id here; it is never overwritten. On a self-hosted instance nothing fills this in for you: either register your own app and put its id here, or email hello@ecency.com to get this site's /auth address registered on the shared app and then put ecency.app here.", }, }, },