This manual is the operator-facing path for connecting Astro pages to Discourse.
It explains the decisions, safe sequence, expected results, and points where an
operator should stop. Use the Machine Manual beside it
when exact commands, fields, scopes, or recovery checks matter.
DiscussionBridge keeps each system doing the job it does well:
Astro or another publishing system owns its fast, structured public pages.
Discourse owns identity, replies, moderation, notifications, and community
memory and is the present operational home for Bridge orchestration.
DiscussionBridge Core maintains the declared relationships, policies,
provenance, jobs, recovery state, and audit evidence.
Astro, Statamic, and future integrations adapt that portable contract to
their publishing systems; they are not independent control planes.
The natural product center is the DiscussionBridge for Discourse plugin,
hosting and operating the portable core through Discourse’s users,
permissions, jobs, UI, database, APIs, and operational machinery. One Discourse
installation may connect to more than one publishing system at the same time.
Tier 1 API-only use remains a useful compatibility path, but operators should
not reproduce separate orchestration policy in every CMS adapter.
Portability is an operator benefit, not merely a code preference. Authorized
people should be able to understand, govern, operate, and move their Bridge
relationships without being trapped by an Astro-specific workflow or another
CMS adapter. The current Astro package proves important domain behavior; the
transition to the portable core, Discourse host, and adapter boundaries is
planned work and is not yet complete.
Everything remains under one DiscussionBridge tent. DiscussionBridge for
Discourse and DiscussionBridge for Astro are fully featured free products.
Public documentation and community support are free, with team help as
capacity permits. Implementation, migration, customization, training,
operations, and extensive hand-holding are paid professional services.
DiscussionBridge SaaS is the paid, managed standalone control plane for
multi-CMS, multi-site, and multi-community orchestration.
The SaaS offering sells managed operation, scale, governance, convenience, and
operational relief. It must not depend on artificial limitations in the free
products. All deployment and service models share the portable Discussion
Bridge Core and preserve operator autonomy.
This is Alpha documentation. Preview every write, keep publishing opt-in, and
verify both systems after a live operation.
Before installing anything, record one row for each content lane:
Decision
Example
Astro site URL
https://docs.example.com
Discourse URL
https://forum.example.com
Content directory
src/content/docs
Route base
empty for docs, blog for /blog/...
Discourse category ID
5
Discourse tags
product,docs
Source mode
astro-managed, discourse-managed, or discourse-imported
Comments mode
simple, full, or fullInteractive
Listing behavior
listed or unlisted
A content lane is one source directory plus its route, category, tags, and
operating behavior. Docs, blog posts, news, and releases should normally be
separate lanes.
Stop if: the public page URL, source owner, category, or managing page is
unclear. A wrong route base or source mode can attach or write to the wrong
discussion.
Write this lane plan down before configuration. The completed row above is a
text-only worksheet example; copy it once for each lane and replace every value.
May publish a new topic and sync its managed first post.
discourse-managed
Discourse
Display or pull from Discourse; do not write back.
discourse-imported
Imported Astro copy
Edit locally if desired, but do not write back until explicitly promoted.
For every discourse-managed or discourse-imported page, add this frontmatter
guard:
discussionSync: false
The named source modes express operating policy, and the CLI write guard is
discussionSync: false. The reviewed Alpha import path generates
discussionSourceMode: discourse-imported, boolean discussionSync: false, and
preserves the topic ID and URL. Review those fields after every import before
running any directory-wide sync command.
Promotion means a human explicitly decides Astro will become the source of
truth, reviews and commits the page and linked topic, changes
discussionSourceMode to astro-managed, and sets discussionSync: true.
Named/multi-target pages must also name the writable target through
discussionPublishTargets and the matching --target. Preview the promoted
page with sync-existing --dry-run --details before the first write. Editing an
imported file or removing only the boolean guard is not promotion.
Stop if: an imported or Discourse-owned page lacks discussionSync: false, or promotion was not explicitly approved.
Create a dedicated bot user, such as discussbridge-bot.
Create or choose the destination category.
Create the planned tags, or confirm the bot can create them.
Add the exact Astro hostname as an allowed embedding host.
Create a granular publishing key for routine publish and sync operations.
Create a separate diagnostics key for setup checks and controlled import
source reads when granular access is insufficient.
For each key, choose User Level and Scope independently. All Users
allows the request to act for the supplied Api-Username; Single User binds
the key to its selected user. Scope separately limits endpoints. Discussion
Bridge supplies the preferred request actor from --post-as,
DISCOURSE_POST_AS, or lane/default postAs/postAsEnv. Legacy
--api-username, DISCOURSE_API_USERNAME, apiUsername, and apiUsernameEnv
remain fallbacks. The resolved actor is sent as Api-Username. Live operations
show Post as: USER; check-discourse shows Request actor.
When creating either key, show its complete purpose block with the setup
instructions and copy that block into the respective protected credential file
above the secret value.
Key user level: Record All Users or Single User and the selected user/actor relationship
Key selected user: Record when User Level is Single User
Request actor: Record resolved postAs / Api-Username used for diagnostics
Key scope: Global or admin-read capable
Operational rule: Do not use in CI/build unless explicitly intended
The settled publishing scopes are:
categories:list
categories:show
posts:edit
posts:list
search:show
tags:list
topics:write
topics:update
topics:read
topics:status
The diagnostics key is currently a global/admin-capable fallback for
check-discourse, controlled troubleshooting, and controlled
import-existing source reads when the granular key cannot read the required
raw first post. Do not place it in CI, builds, runtime publishing, or deployment
configuration. Load it only into the controlled operator session, never print
it, and remove it after the read/import operation.
Store key values only in a credential vault, session environment, or hosting
provider secret store. Never place them in source files, screenshots, issues,
chat, or build logs.
See Key Management for the complete credential-file
templates, including description, scope, granular permissions, and the secret
placeholder.
Stop if: the routine publishing key is broader than intended without a
recorded reason, the diagnostics key is configured as the normal publishing
key, or a real key appears in a file or screenshot.
Verify the granular-key screen shows only the settled User Level and publishing
scopes. Record the scope names as sanitized text; never capture or expose the
key value or private account details. A screenshot is optional and must be
reviewed for secret safety before retention.
Create a special-admin custom group as the visible inventory for nonhuman
admin/service accounts. Then assign actual admin, category, and API authority
separately; group membership grants none of those by itself.
For connected forums, prevent actual and visually ambiguous service-account
collisions. Candidate forum-source editors are editorbridgeforum /
DiscussionBridge Forum Editor and editorcanforum / CAN Forum Editor.
Verify normalized username length and availability before creation.
Astro-origin actors should identify the source site or brand; keep established
obbba-bot as the OBBBA source identity.
Alpha is distributed through an immutable asset attached to an accepted GitHub
prerelease. Copy the exact tag, asset filename, SHA-256, and npm integrity from
that release record. Download the asset, verify it, and install that same local
file; do not substitute an npm registry version or make npm fetch a second copy.
Use preset: "starlight" for Starlight and preset: "astro" for broader
Astro sites. Keep publishOnBuild.enabled false until the lane has passed
explicit CLI dry runs and a controlled live test.
For Starlight placement and the layout override, follow
Alpha Setup. You should see the Astro site build normally
and the discussion area appear only on pages with linked topic metadata.
Set these in the shell running the command or in a protected CI/deployment
secret store:
DISCOURSE_URL
SITE_URL
DISCOURSE_POST_AS
DISCOURSE_API_USERNAME
DISCOURSE_API_KEY
DISCOURSE_DIAGNOSTICS_API_KEY
DISCOURSE_DIAGNOSTICS_API_KEY is optional. When absent,
check-discourse falls back to the publishing key and may report metadata as
unavailable rather than failing.
All Bridge authorization uses user-created Discourse API keys. A named Bridge
machine identity is a durable operating record for one of those keys and its
Discourse actor, scope, owner, storage reference, audit policy, and rotation
policy. It is not an alternate credential system. Routine operations reuse the
appropriately scoped key; they do not create or revoke a key per run.
Prefer DISCOURSE_POST_AS; retain DISCOURSE_API_USERNAME only for backward
compatibility. postAs selects the request actor but does not silently change
ownership of an existing topic.
You should be able to run a command without printing any key value.
You should see discovered limits, tag capabilities, category details, setup
issues or warnings, and reconciliation details when --page-url is present.
Warnings about unavailable site metadata mean the key could not prove the
setting; they are not permission to guess.
Page-URL reconciliation and explicit existing-topic linking are different:
When a page supplies discourseTopicId, that topic ID is authoritative for
the native/full-app embed. A page-URL embed-info 404 or exact search with no
owner does not invalidate a healthy explicit topic.
When no topic ID is supplied, the embed uses the page URL and URL ownership
must reconcile correctly before release.
Always verify the explicit topic directly as well as recording any independent
page-URL reconciliation result.
Pages without discourseTopicId and pages with discussionSync: false are
skipped. Use --force only when deliberately rewriting a first post despite an
unchanged source hash.
Files may use either LF or Windows CRLF line endings. The bridge recognizes both
frontmatter forms and preserves the existing style when it updates frontmatter.
If a valid linked page is unexpectedly reported as not linked, stop before any
write and check frontmatter-boundary parsing rather than relinking the topic.
Both read-side guard recognition and write-side line-ending preservation are
covered by regression tests.
Choose discourse-managed when edits continue in the source topic. Omit
--source-mode or use discourse-imported for the imported-copy default.
astro-managed is rejected because import is a Discourse-to-Astro operation.
discussionSourceMode: discourse-managed
discussionSync: false
You should see the selected source mode and discussionSync: false generated
with a Markdown file linked to the original topic. Review the imported body and
frontmatter before building or editing. Avoid --overwrite unless replacement
is intentional and recoverable. A manifest entry may use sourceMode to make
the same selection per topic.
Stop if: a dry run shows an unexpected page URL, topic ID, target,
category, managing page, overwrite, or writeback-eligible imported page.
To place a hero image at the start of an imported page:
--hero-image and --hero-alt are a required pair. Alt text must contain
meaningful non-whitespace text. The generated Markdown places one angle-wrapped
leading image before the unchanged raw topic body; internal path spaces and
escaped alt text are supported.
Stop if: only one hero option is present, alt text is empty/whitespace, or
the hero insertion changes the normalized Discourse body.
To remove the known trailing community call-to-action block during import:
This opt-in profile removes only a trailing block after a horizontal rule when
all four markers are present: Join the Conversation Today, /signup, Please share how, and /c/stories/. Without a verified boundary, import stops before
writing a file. Unknown, duplicate, bare, or empty profile inputs also fail
before file I/O.
You should see discussionImportPolicy: "pruned:community-call-to-action" only
after a successful profiled import.
Import discovery/queue is required for Alpha. Use either:
an explicit topic list or manifest for curated imports; preserve the order the
operator supplied;
“next in category” for queue work. First list/discover available categories,
including subcategories, then select by category ID or an unambiguous
slug/name. Preview that category’s queue and choose the oldest Discourse
created_at, using topic ID as the stable tie-breaker.
After category selection, optional filters may narrow tags, created-date range,
open/closed status, and result limit. Operators may request oldest-first or
newest-first ordering, but both use created_at.
For numbered collections whose created dates are unreliable, Alpha may use
natural topic-title/name ordering (for example, Section 10102 before 10103).
This never permits ordering by latest activity.
Always preview the candidate list before importing and exclude topics already
represented by imported Astro pages.
Use the read-only discovery command before import:
Use --list-categories first when you need IDs, exact slugs, names, parent
relationships, and topic counts. Add --include-subcategories only when the
selected lane should include descendants. Other optional controls are
--created-from, --created-to, --status all|open|closed, --order oldest|newest|natural-title, --limit, and --json.
The command previews only; it never imports. It recursively excludes topic IDs
found in opening-frontmatter discourseTopicId or strictly parsed
discussionTargetBindings; unrelated topicId metadata remains eligible.
Descendant categories are fetched directly and deduplicated. A date-only
--created-to includes that entire UTC day.
Add --manifest-out FILE to save the reviewed order as a new strict v1
manifest; the command refuses to overwrite an existing file. All runtime
source-mode/comments-display validation finishes before network or local
scans, and manifest validation finishes before dereference or filesystem work.
Generated entries default to discourse-imported, with optional
discourse-managed source mode and an explicit comments display. Public
categories need neither a site URL nor credentials.
Final reviewed evidence is Code Boss PASS and 84/84 tests plus a live read-only run
against the Cloudflare-CDN-backed Repeal OBBBA forum: category 18, TITLE-I,
natural-title order, and limit 10 scanned 320 topics, excluded five already
imported topics, and previewed topics 754, 755, 756, 757, 758, 759, 761, 762,
763, and 764. No file was written.
The OBBBA worked example then saved those ten candidates as a tracked strict v1
manifest, applied a uniform source/comments/tag/hero/alt/prune policy, and ran a
credentialed read-only manifest dry-run. Expected evidence was 0 imported, 0
skipped, 10 dry-run, and generatedPages=0.
The live gate later passed for those exact ten topics: 10 Astro files imported,
zero Discourse writes, clean build, corrected deployment, ten live HTTP-200
routes, and three removed stock routes returning 404. Topic 754 was readable at
/t/754.json, but its first post lacked raw Markdown. Fetching that first post
by post ID at /posts/761.json returned 403 with the granular key; 761 in
that endpoint is the post ID, not the separate topic 761 in the batch. The
controlled retry used the protected diagnostics key in memory. Keep
that key out of CI/build/runtime publishing and deployment configuration.
For deterministic refresh of pages with different policies, use the reviewed
Alpha import manifest rather than a blanket update-all operation. Its strict
JSON contains only version and ordered imports. Each topic entry retains its
own commentsDisplay, heroImage/heroAlt, and pruneProfiles, and caller
order is preserved. Run import-existing --manifest ... --overwrite.
Preview before writing. The bridge rejects duplicate topics and mixing manifest
mode with direct topic options, revalidates every entry, checks destinations and
path containment, and stages the whole batch before atomic creation or
overwrite rollback. A failed batch must not leave a partial import set.
Treat every import as two joined contracts:
WHEREFROM: the Discourse base or target, explicit topic or curated order,
category when the lane uses one, and required tags or filters;
WHERETO: the Astro content root, explicit output file, public route, and
Astro navigation lane, with the site URL fixed as part of public identity.
Validate the source identity and live tag constraints before writing. Make the
destination deterministic, reviewable, and contained inside the content root.
Manifest v1 keeps these as the existing flat fields—such as topic,
requiredTags, and output—rather than a new nested structure. A nested
from/to form is only a possible future evolution.
If the source topic later moves to another Discourse category, Discussion
Bridge reports:
source category changed: OLD -> NEW; Astro route/navigation unchanged
An overwrite refreshes discussionSourceCategoryId, but it does not silently
move the Astro file, public route, or Astro navigation lane. WHEREFROM changed;
WHERETO remains an explicit operator or manifest decision. Review and change
the destination separately only when that is the intended publishing decision.
Never use:bumped_at, last reply, or latest activity for queue order.
Community participation must not reorder publishing candidates.
Replies and likes render; browser refresh works through CORS or a proxy.
fullInteractive
Logged-in reply, like, quote, and moderation should remain inside Discourse.
Full-app embed, sign-in, iframe height, and mobile behavior work.
For Alpha, use simple or full for plugin-free public production. Core-only
fullInteractive is a compatibility/development preview. Production-quality
comments-only fullInteractive requires DiscussionBridge for Discourse after
its controlled-creation and embed capabilities pass. The Astro package does not
install that plugin. For an ordinary consumer forum, a human Discourse
administrator installs the exact published plugin identity, rebuilds app for
a standard single-container forum or only web_only for the official
two-container layout, and proves that forum healthy with all DiscussionBridge
settings still off. The final Alpha release gate separately tests both
topologies on the named acceptance hosts described below. simple and full
remain plugin-free.
For full, configure a same-origin refreshEndpoint when browser CORS does not
allow direct topic JSON reads. For fullInteractive, enable Discourse’s full-app
embed settings and test both signed-in and signed-out users.
fullInteractive uses dynamic iframe sizing by default. The iframe begins at
embedHeight: "800px", then follows Core’s content reports between
embedMinHeight: "360" and embedMaxHeight: "900". The adapter does not add a
CSS viewport ceiling: the Alpha.5 human pass proved that a competing 70vh
maximum can clip topic-progress and composer content at the host boundary.
Operators may tune the three supported values or set dynamicHeight: false for
a fixed-height embed. The deprecated embedViewportMaxHeight option accepts
only "none"; any other value fails configuration. Verify topic-progress,
scroll, short, long, composer-open, desktop, and mobile states.
To close a live signed-in interaction item, create one clearly labeled test
reply through the browser, then verify its public post URL, content marker, and
updated topic count. Recheck the Astro page’s topic/full-app signature afterward.
Record the evidence without publishing private account identifiers.
An existing-page interaction result does not prove a fresh-import workflow.
Before closing an import gate, separately test: no hero/no prune, hero only with
alt text, prune only, and hero plus prune. For every case, verify generated
source-mode guards, preserved topic linkage, build/deploy/live rendering,
comments, and no accidental writeback.
For an existing topic, pass its topic ID through the complete component path.
The native embed should configure { topicId } when it is present and fall back
to { discourseEmbedUrl: embedUrl } only when there is no explicit topic ID.
Rendering ownership changes by comments mode. The package’s Astro-rendered
full mode now has reviewed first-generation parity: Mermaid replies render
client-side by default, and tables receive readable styling plus horizontal
overflow handling. Set replies.renderMermaid: false to opt out. Mermaid is
loaded only when a reply needs it; a load or render failure preserves the source
code for recovery instead of destroying the reply.
In fullInteractive, the cross-origin iframe belongs to Discourse, so Astro-side
Mermaid transforms and CSS cannot render or restyle content inside it. The
ordinary topic view may render Mermaid while the full-app comments embed still
shows raw Mermaid source because the embed application does not load normal
theme-component JavaScript. Use Discourse embedded CSS, targeted with the bridge
embed class hook, for immediate table presentation. Mermaid still needs a
Discourse-side embed extension, plugin, or upstream solution; do not mark it
fixed.
For each mode, verify the rendered discussion at desktop and narrow/mobile
widths using the mode table above. For fullInteractive, sign in through the
embedded forum, post a reply, return to the Astro page, and confirm the reply is
present and ordinary forum behavior is unchanged. Keep sanitized evidence of
the tested route and viewport; screenshots or video are optional evidence, not
unfinished manual content.
DiscussionBridge displays Connected by DiscussionBridge after the complete
discussion surface by default. Only DiscussionBridge is linked. The credit
works across all three comments modes, remains outside the Discourse iframe in
fullInteractive, inherits host-site theme tokens, and includes equivalent
hover, keyboard-focus, and reduced-motion behavior.
Disable or customize the escaped plain-text credit through comments.credit.
Its link must be an absolute HTTP(S) URL. The setting is independent of
Discourse’s Powered by Discourse control and never changes comments behavior.
If src/content/blog/example.md renders at /blog/example/, use:
Terminal window
--route-baseblog
The page URL is part of the Discourse ownership contract. Check it in
--details output before every lane’s first live write. Only one Astro page may
manage a topic in a run; comparison pages should use discussionSync: false.
Keep Astro/template content tags separate from Discourse discussionTags
unless an explicit mapping is introduced later.
DiscussionBridge does not require Cloudflare Pages, but the Alpha demos use it.
For a static Astro site:
Build from the canonical repository and the intended site/example root.
Use the project’s normal install and npm run build commands.
Confirm the output directory matches the Astro/Cloudflare project settings.
Set the final public URL in Astro site and DiscussionBridge siteUrl.
Attach the intended custom domain and wait for HTTPS to become valid.
Add that exact hostname to Discourse’s allowed embed hosts.
Verify the homepage, a lane route, its companion topic, and comments.
When Workers are used, verify both the Worker endpoint and canonical domain.
Confirm the deployed page has the expected package/topic signature and that
any retired renderer is absent.
If more than one Cloudflare account is available, the approved site deployment
configuration should pin the intended account so deployment is repeatable. Keep
private account labels and login addresses out of public manuals and screenshots.
Before making a deployment-only commit, inspect the site worktree. Preserve and
report unrelated pre-existing edits instead of silently including them.
Also build the exact committed candidate from a clean checkout or detached
worktree. A local file deletion can make a dirty build look healthy while the
tracked release still contains the stale page. If the clean build finds one,
isolate the removal or repair in its own reviewed commit and build again.
If the deployed page looks stale, verify the deployment commit and Discourse
topic first. Then test with a cache-bypassing request or clear only the relevant
Cloudflare cache. Do not treat a confirmed sync as failed until cache state is
ruled out.
DiscussionBridge has now been tested against the production
Cloudflare-CDN-backed Discourse deployment at forum.repealobbba.org.
Diagnostics/API reads, topic imports, target reconciliation and source-topic
links, fullInteractive comments, signed-in replies, five live source notices,
and no-writeback behavior all passed in that bounded environment.
This proves compatibility with that production deployment, not every possible
CDN, WAF, or cache rule. When placing Cloudflare in front of Discourse, preserve
Discourse API paths and JSON endpoints, embed and full-app routes,
authentication/cookies, and websocket behavior. If API or embed behavior differs
from a direct-origin check, investigate cache and WAF handling before treating
the bridge as broken.
Stop if: the deployment uses a transitional copy instead of canonical
source, the custom domain differs from siteUrl, HTTPS is invalid, or the
Discourse embed host does not exactly match the public hostname.
CLI summary reports the expected created, updated, skipped, or unchanged count.
the topic title, category, tags, and listing state are correct;
the first post contains the intended reader-facing content and source link;
frontmatter contains the expected topic link and sync metadata;
the Astro page and full-discussion link work;
comments work in the chosen mode;
no secret appears in source, output, screenshots, or support material.
Never automatically recreate a deleted topic or first post. Confirm whether the
deletion was intentional, then choose restore, relink, or replacement explicitly.
See Troubleshooting for known failures and recovery
guidance.
Use this exact recovery sequence:
Preserve the current Astro source in Git and record the old topic ID/URL.
Run check-discourse --page-url with the diagnostics key and
sync-existing --dry-run --details.
Restore an accidentally deleted topic/first post with Discourse’s own staff
controls whenever that identity should remain.
If replacement is intentional, verify ownership/category/permissions, then
update topic ID and URL together (and the selected target binding when used).
Never choose a replacement because its title merely looks similar.
If creating a new topic is the reviewed decision, remove stale linkage in a
committed source change, retain the prior values in Git history, then run
publish-new --dry-run --details before the live create. Plugin-managed
lanes may require administrator disposition of the stale mapping first.
Verify the final Astro route, topic, first post, embed, category, tags, and
listing state. For multi-target failures, retry only the failed target.
Code completion alone does not make a release ready. For every Alpha, Beta,
release candidate, patch, and Current release, the release record must show:
Code Boss reviewed the exact release candidate and recorded pass or fail.
All blocking code-review edits are complete and re-reviewed when required.
Bridge Boss completed technical verification.
Manual Boss completed documentation quality review.
The Human and Machine Manuals are ready for the exact release.
Product Boss documentation sign-off is recorded.
Product Boss release approval is recorded.
These last two decisions are different:
Product Boss documentation sign-off confirms that the manuals and product
docs accurately describe the proposed release.
Product Boss release approval confirms that the release is coherent across
intended scope, operator readiness, known limitations, and its documentation
package.
Product Boss release approval does not replace Code Boss review, Bridge Boss
technical verification, or Manual Boss quality review. A failed, unresolved, or
edit-pending Code Boss review blocks Product Boss approval.
Stop if: any required review is missing, a blocking edit is unresolved,
the manuals describe a different build, or either Product Boss decision has
not been recorded for the exact release candidate.
The cumulative Alpha feature/function set is locked in the product checklist.
After the lock, work belongs in Alpha only when it closes an existing promise or
gate, fixes tested behavior, or is approved explicitly as a scope change.
Unchecked Alpha gates still need to be finished; the lock does not mark them
complete.
Alpha should honestly represent the major capabilities in its declared product
promise and be nearly feature-complete for that promise. Beta should primarily
refine real-user experience, compatibility, reliability, performance,
packaging, documentation, installation, recovery, support, and presentation.
This does not move every future or Layer 3 idea into Alpha.
Tier 1 operation remains API-only, free/self-serve, and independent of a
Discourse plugin as a compatibility capability. The settled architecture makes
DiscussionBridge for Discourse the natural forum-governed home for policy and
orchestration. The current Alpha implementation provides authenticated
create-or-resolve, a configured non-system operating identity, forum-owned
category/tag authority, durable reservation and source mapping, forced-unlisted
controlled topic creation, requested-versus-effective policy, and audit. It is
installed and accepted on stable preproduction
dev-forum.discussionbridge.dev at plugin SHA
50c4a92359f672a00b2242e99819a70813ebea19 in the official split data +
web_only topology. Installation, migrations, safe-default startup, reviewed
settings, create-then-resolve, comments-only presentation, ordinary-topic
isolation, admin operations, disable/re-enable, record-only upgrade, and
rollback to the qualified SHA passed on 2026-08-22. The endpoint is disabled at
rest. Local/sandbox results remain dated qualification evidence; they are not
the current installation state and are not a public release.
The remaining plugin release gate is human Discourse administrator installation
of the exact publicly published Alpha tag/SHA from the public instructions on
both named acceptance hosts: the standard single-container app proof on
sandbox-forum.discussionbridge.dev and the official split data + web_only
proof on dev-forum.discussionbridge.dev. Each host/topology must prove its own
rollback identity, installed SHA, migrations, safe-default startup, ordinary
forum health, approved enable/configure behavior, and topology-matched
rollback/removal. forum.repealobbba.org is not a substitute or third current
release-gate install; any later independent real-world proof there requires
separate OBBBA authorization and recovery acceptance. Another generic
nonproduction install is not the gate. Post-as-user, PM
automation, existing-topic migration, and broad unattended forum-to-forum
administration remain outside this boundary.
The CAN normal-topic baseline may continue to use the Discourse Mermaid theme
component. The next plugin boundary is the published-candidate human
installation release gate, plus any
separately designed Mermaid/table parity still needed inside the full-app
embed. This does not change Tier 1 installation.
Discourse Mermaid is the official theme component documented at
Meta topic 218242 and
discourse/discourse-mermaid-theme-component.
It is not a plugin. Keep it distinct from a fork/extension of that theme
component, the separate optional DiscussionBridge for Discourse plugin, and
an upstream Discourse change.
The plugin is a separate product/repository under Boss routing. Its v0.1 Alpha
goal is installable and removable on supported stock/current Discourse with
documented rollback, no ordinary-topic regression, controlled topic creation,
and a later live comments-only full-app proof. Full broad forum-to-forum
administration, arbitrary post-as-user, and PM automation remain out.
Alpha scope is cumulative. Plugin and multi-target work add to every previously
accepted Alpha gate; they do not rewrite or shorten the promise. Use the existing
dashboard and build/launch checklists as the complete source of truth, and remove
an item only when Phil explicitly directs that change.
All three Alpha software tracks remain free/open source unless explicitly
changed later: the Astro package, the DiscussionBridge for Discourse plugin, and
public docs/community support. Paid offerings are implementation help,
handholding, managed hosting/operations, customization, support, and
consulting. Third-party hosting and infrastructure remain operator-paid.
Alpha must demonstrate the product loop in both directions without creating a
two-writer loop:
Publish an Astro-managed discussionbridge.dev blog post to a public
companion discussion on forum.discussionbridge.dev.
Republish a reviewed community wiki/how-to from
forum.discussionbridge.dev as a durable guide on
discussionbridge.dev.
For the wiki lane, use discourse-managed plus discussionSync: false, show
source provenance near the article start, preserve the source topic as the
primary discussion, and define the output route and Astro navigation lane
explicitly. Refresh deterministically from the wiki topic. Editors change the
wiki in Discourse; the site republishes the reviewed source. Do not imply that
replies from separate topics are merged.
You should see: a public guide with a clear source link, an explicit
primary discussion, and predictable navigation placement.
Stop if: the site is able to write back to the wiki source, the source
topic changes unexpectedly, the destination route drifts, or comments
presentation silently selects or merges discussions.
The public outcome is: “The site starts conversations. The community develops
durable knowledge. The site publishes what the community learns.”
Implementation and Code Boss review are complete at 1731547 with 72/72 tests.
Apex adoption commit d68ffc4 also received Code Boss PASS, passed a clean
detached install/build that generated five actual public apex routes, and was
deployed on 2026-07-23. This is distinct from the readable product-docs build,
which synchronized 20 documentation sources and generated 21 HTML pages in this
documentation pass.
Astro-managed blog ──publishes──▶ Forum topic 37
Forum wiki topic 36 ──publishes──▶ Discourse-managed Astro guide
Visuals derived from this diagram must use alt text that names both directions
and says the reply streams remain separate. Do not include admin screens,
credentials, tokens, account identifiers, or protected storage in screenshots
or video.
Live verification shows:
/blog/every-connection-has-a-job/ returns 200 and binds its independent
public companion discussion to topic 37;
/guides/how-to-choose-a-discussion-bridge-source-mode/ returns 200, shows
source disclosure, and renders source wiki topic 36 as the primary
fullInteractive discussion;
a deliberate guide sync-existing --dry-run skips with the
discourse-managed no-writeback reason;
the raw Pages hostname redirects to the canonical apex.
This closes the bounded two-direction dogfood gate. It does not claim merged
reply streams or general forum-to-forum orchestration. The clean install still
reported one high-severity npm audit finding, and the Mermaid chunk remains
larger than 500 kB; neither was hidden or changed with an automatic audit fix.
See the
sanitized verification record
for the live markers and claim boundary.
The topic-36 editor-ownership acceptance test remains open. A human operator
must change the wiki first-post owner from discourseadmin to the selected
DiscussionBridge Forum editor, edit the wiki while signed in as that editor,
re-import/refresh the discourse-managed guide with overwrite, then verify
content and source ownership, build/deploy/live markers, and no Astro
writeback. Actor configuration alone does not complete this test.
Imported pages may now show Source author: Display Name (@username) when
Discourse exposes safe author data. The username links only to the same forum’s
safe /u/username profile, preserving a Discourse subfolder base when present:
https://example.com/forum/t/... becomes
https://example.com/forum/u/editorbridgeforum. Unsafe usernames are omitted
rather than linked.
An explicit overwrite refresh updates discussionSourceAuthorUsername and
discussionSourceAuthorName while preserving source mode,
discussionSync: false, and topic ID.
The Alpha multi-target model is implemented and reviewed. The first two edges
of the bounded live topology proof are complete; the wider matrix still tracks:
the same selected onebigbeautifulbill.us page → forum.repealobbba.org;
that same selected page → forum.citizenactivist.network;
The first two prove one Astro page can explicitly connect to several forums; the
last proves many sites can converge on one forum. Citizen Activist
Network’s forum identity is “A community of activists.” Its Cloudflare/account
ownership placement remains an Ops decision.
Live adoption commit 36df91c98a35251edd6ddd657cca42ddf0acdafa proves the
same 10101 page can retain Repeal OBBBA topic 434 as protected source and primary
fullInteractive discussion while linking an independent Citizen Activist
topic 9 under accessible Additional discussions navigation. Diagnostics,
target-specific dry-run, publication, unchanged retry, clean build, deployment,
live checks, and no-source-writeback verification passed.
Use the narrowest correct content root. For this lane it is
src/content/docs/title i with route base title-i and active target
citizen-activist. An earlier broad dry-run exposed a wrong root/index and a
malformed title-i/title i route before any write. Treat previewed route drift
as a stop condition, correct the lane, and rerun dry-run.
Keep credentials in protected storage. Do not copy storage paths, account
values, or secrets into public docs. Existing record-format cleanup belongs in
the protected vault. The exact clean install reported 10 dependency audit
findings (1 low, 1 moderate, 8 high); route them for dependency review and do not
apply an automatic npm audit fix.
Post-proof interaction remained correctly separated: Citizen Activist topic 9
accepted a live reply as post 2, while the Astro page continued embedding
protected/primary Repeal OBBBA topic 434. Readers could reach the independent
Citizen Activist conversation through the accessible Additional discussions
link. This is interaction/presentation evidence for the closed bounded gate,
not a broader topology claim.
The page must distinguish its protected source target from its ordered
publication/discussion targets. Review each target’s forum, topic binding, sync
and error state, and display policy independently. Keep the imported/managed
source protected from writeback while allowing explicitly approved publication
to another forum.
In frontmatter, list the page’s targets in order with discussionTargets, then
name only writable destinations in discussionPublishTargets. Identify the
protected imported/managed source with discussionSourceTarget. The bridge keeps
each forum’s result independently in discussionTargetBindings.
If more than one discussion is linked, choose discussionPrimaryTarget. You
should see that discussion rendered in the selected comments mode and the other
targets as accessible named links. Optional targetLabels can make those link
names friendlier. Stop if a multi-linked page has no explicit primary; the build
error is protecting the operator from a silent choice.
Run the CLI once per explicit --target. If one target fails after another
succeeds, keep the successful binding and retry only the failed target. The
stored failure is target-specific and sanitized. Do not manually discard a
successful binding or create a replacement topic merely because another target
failed.
Choose the primary rendered discussion and state whether additional targets are
linked or rendered; never let the bridge silently select one. If one target
fails, keep successful bindings, report the failure, and retry only that target
idempotently without duplicate topics. Diagnostics, previews, CLI output, and
live checks must identify the target. General administration remains later.
Every connection has a job. A reader should understand whether
an additional discussion is for the public community, a chapter or region,
internal review, subject-matter feedback, advocacy coordination, or syndication.
Use that purpose in its visible label and call to action. Never imply that
independent replies have been merged.
Lead with the outcome: “Publish from the site. Learn in the community. Turn what
the community knows into durable pages.” Content can begin on either side;
discussion stays where the people are, and durable knowledge can be published
where readers can find it. A destination-only label is not enough.
Possible reader-facing patterns are Discuss with the Citizen Activist
Community, Review with the policy team, Discuss with your state
chapter, and View the source wiki, each followed by a short audience and
context explanation.
CAN can support Astro-to-Discourse and Discourse-to-Astro flows, but only with
separate page/topic pairs and explicit source ownership. Stop if the same item
would be writable in both directions; choose one writer and protect the other
side. Relay, promotion, and summary automation are later features.
Another future pattern is Local ownership. National reach. A chapter can
turn local experience into network knowledge without giving up its community,
context, or voice. The national community can discover and discuss chapter work
while every topic remains connected to where it began. Local and national reply
streams stay separate: one serves local coordination/context, the other national
learning/amplification.
The likely reverse path distributes national campaign guidance into selected
chapter forums for local discussion. Before enabling either direction, require
mapped categories, chapter/region metadata, public/private eligibility,
moderator approval policy, source attribution/return links, explicit one-way
updates, and clear moderation owners. General forum-to-forum orchestration is
future design, not current capability.
12. Show Where Discourse-Sourced Content Came From
Pages imported from or managed in Discourse should disclose their source near
the start of the article. This notice is separate from comments and from any
DiscussionBridge credit at the comments boundary.
Wire DiscussionSource into the canonical page boundary:
The plain Astro BlogPost layout and Starlight MarkdownContent override are the
canonical placements. You should see a quiet aside labeled Content source
with a bold Source: prefix:
discourse-imported: “This page originated in Discourse and was imported
here for publication.”
discourse-managed: “This page is managed in Discourse and published here
for easier reading.”
astro-managed or unknown mode: no notice.
sourceLabel defaults to Discourse. Use sourceLabel, message, and
linkLabel to adapt public wording without hiding provenance. Other component
inputs are class, mode, sourceUrl, targetBindings, and frontmatter.
The source link follows this order: explicit sourceUrl,
discussionImportedFrom, the protected discussionSourceTarget binding (with
legacy discussionTarget fallback), then legacy discourseTopicUrl. Only
absolute http or https URLs become links. If every candidate is unsafe or
malformed, the disclosure remains visible without a link.
Stop if: a multi-target page attributes its origin to an additional
publication target. Provenance must always follow the protected source target.
Package behavior is implemented and reviewed at a9d2097 with Code Boss PASS
and 68/68 tests. OBBBA adopted reviewed artifact
astro-discussion-bridge-0.1.0-alpha-a9d2097-f3fbb73e.tgz at commit aa7846d.
Its clean production build and deployment passed. All five canonical Title I
routes now show exactly one Content source aside and one source link, with
the imported wording, Repeal OBBBA Forum label, and correct protected
forum.repealobbba.org topic. The existing discussion boundary remains present.
This closes OBBBA source-disclosure adoption only; it does not close the separate
Citizen Activist topology gate.
The public Alpha channel is one GitHub prerelease with an attached package
tarball built from the exact accepted Astro-package commit. npm registry
publication is a later, separately authorized gate; Alpha instructions must not
use an npm dist-tag, latest, or an unversioned registry install.
The release record must name the exact tag, source commit, asset filename,
tarball byte size, SHA-256, npm integrity, and package inventory. Consumers
download the asset, verify its SHA-256, install that exact local file, and bind
the resulting lockfile to the accepted npm integrity:
if ($installed.resolved-notmatch [regex]::Escape($asset)) { throw'Lockfile does not resolve the verified asset' }
if ($installed.integrity-ne'<expected-npm-integrity>') { throw'Installed package integrity mismatch' }
Never replace or delete a published Alpha asset in place. A correction receives
a new prerelease tag and asset. A repository checkout or moving branch is not a
release identity.
Plugin-backed fullInteractive has an additional release gate. After the exact
plugin candidate is published through its GitHub prerelease/install channel,
human forum administration—not the implementation agent—must install that exact
tag/SHA using only the public instructions on both named acceptance hosts: the
single-container app sandbox at sandbox-forum.discussionbridge.dev and the
split data + web_only stable-preproduction forum at
dev-forum.discussionbridge.dev. Each host/topology acceptance record must
prove rollback identity, installed SHA, migrations, safe-default startup,
ordinary forum health, the documented enable/configure flow, and understandable
disable/rollback/removal. forum.repealobbba.org remains outside these two
current proofs and requires a later, separately authorized independent
real-world gate. Release acceptance cannot close without both human PASS
records. A failure creates a new corrected prerelease; it never rewrites the
tested release identity.
Published plugin v0.1.0-alpha.5 is immutable REJECTED — DO NOT INSTALL
evidence. Its real Astro-hosted gate found that qualified Core shows a profile
summary but no embedded Log Out control; the automated test had synthesized
that unreachable trigger. The adapter’s competing 70vh ceiling separately
clipped topic-progress/composer content. A corrected gate must prove the lower
frame and credit boundary, visible Post reply/Save edit, Reply, Like,
Quote, edit, signed-out initial state, sign-in, and new-user sign-up. Session
loss is induced separately through Core-owned logout/session behavior, followed
by reloading the known mapped Astro page; Open discussion is an external
handoff, not an embedded logout control.
Before upgrade, record the installed asset filename/integrity and lockfile,
start from a clean consumer worktree, download and verify the new asset hash,
install that same local file with --save-exact, verify the resulting lockfile
resolution and integrity, then run package tests, the consumer build,
check-discourse, dry-run sync, and one bounded deployed smoke. Stop on a hash
or integrity mismatch, unexpected package inventory, dependency drift, build
failure, Discourse diagnostic failure, or discussion regression.
Rollback selects the last accepted prerelease, downloads and verifies its
recorded asset hash, installs that exact verified local file with
--save-exact, verifies the restored lockfile integrity, and repeats the
build, diagnostic, deployment, and public discussion checks. Restore the prior
lockfile when it is part of the accepted record. Mark a bad prerelease as
superseded with a warning; do not replace, delete, or silently rewrite its
asset. Never run an automatic npm audit fix during release or recovery.
Run the full package suite against the exact built release candidate. Its
passing result includes the automated full attribution gate, covering
root/package MIT parity and holder, package metadata, production dependency
licenses against the explicit allowlist or reviewed override evidence,
required npm package contents, README/non-affiliation and rendered links,
tracked-media provenance, and protected-path scanning. Record the exact suite
total in the candidate-specific evidence.
The readable docs build runs a narrower gate. You should see:
Attribution and licensing gate: PASS (docs scope)
npm package contents: SKIPPED (requires built release candidate)
The synchronized-source and generated-HTML totals mean synchronization,
rendering, and this bounded docs-scope check passed. Record the exact totals in
the candidate-specific evidence. This result does not verify the release
tarball and does not replace the full package gate.
Stop if: either gate fails, the results are conflated, generated
attribution output was not regenerated on a fresh checkout, or a
protected/private path appears.
Automation cannot decide whether attribution is adequate or whether copied,
adapted, branded, or sourced material is appropriate. Before release, Manual
Boss must record Attribution and Licensing: PASS / FAIL / N/A, list the paths
reviewed, and create a sanitized review record tied to the exact release
commit.
For candidate b09dbce atop 7127eb1 and 462b3ae, Manual Boss recorded
Attribution and Licensing: PASS with no remaining findings or blockers. Read
the sanitized exact-candidate review record.
This PASS applies only to that exact candidate; it does not pre-approve later
release changes.
The intended support split is:
GitHub Issues for confirmed bugs, reproducible failures, docs gaps, and
feature work;
alphasupport@discussionbridge.dev as planned email intake, not active until
its Discourse route is separately verified;
paid help for private implementation and migration work.
The live support category and email route remain release prerequisites until
verified. Never include keys or credentials in a support report. Follow
Support And Feedback for the sanitized diagnostic
fields to include.
DiscussionBridge should make a complete body of structured content reachable
without expanding the entire hierarchy on every page. For the proposed OBBBA
redesign, Bill Structure contains separate content lenses: OBBBA Text
first, Impact second, and Law as Amended later when suitable.
Choose navigation authority per lane before joining discussion metadata. For
official-source lanes, the authoritative external source defines scope,
hierarchy, order, labels, and local routes. Local hierarchy/group nodes may
exist without a Discourse topic. Never create a synthetic topic merely to make
navigation valid. When a node claims a forum connection, it must provide the
complete reviewed topic ID and source URL together; partial bindings fail
closed.
For forum-authored lanes, categories, tag groups, index topics, and content
topic tags may still define the lens and hierarchy. Do not assume tag-group
member order is authored order, publish workflow tags automatically, or apply
forum-derived structure to an official-source lane.
The recommended reader experience is complete structure with progressive
presentation: show lenses and Titles globally, then expand the current lens,
Title, and active Subtitle/Chapter/Subchapter/Part branch. Keep other branches
collapsed but user-expandable. Use index pages for the complete outline, and
provide breadcrumbs, authored previous/next, and search.
You should see: the active branch immediately, the full structure through
index/browse pages, and predictable routes such as
/obbba-text/title-i/... for official Text and /title-i/...-impact/ for
preserved Impact pages.
Stop if: hundreds of inactive Title VII links appear on every page or in
unnecessary DOM content; the mobile drawer loses the active branch; keyboard
or screen-reader navigation fails; workflow tags leak into public
navigation; or tag-group response order overrides authored index order.
The current OBBBA Text promotion candidate derives 310 enacted section pages
and their hierarchy from GovInfo Public Law 119-21. It joins 307 complete
optional forum bindings only after that official inventory exists. Sections
1, 20009, and 71119 are valid local official pages without forum topics;
Section 70310 is absent. The frozen candidate contains 331 unique sitemap
routes, and every official navigation destination is a sitemap member. Impact
remains a separate preserved lens with 15 local routes.
Still open: exact deployment authorization and live acceptance for the
reviewed Text candidate. Law as Amended remains a separate clean-room lane.
The inherited Law as Amended implementation was abandoned on 2026-07-27.
Treat it only as inert lessons-learned provenance. Do not repair it, copy its
schemas or fixtures, or use its parsers, caches, cardinalities, generated
evidence, or derivative models as the new starting point.
The replacement begins empty. Authoritative external official sources establish
scope and legal state first. Only after that review may Discourse add:
an optional section topic title, preserved verbatim;
optional tags, category, and authored-index organization;
legislative-drafting context; and
an optional discussion topic binding.
Forum bodies, OBBBA Text, local derivatives, diagnostics, legacy caches, and
the historical 309-item forum inventory cannot define legal content, official
scope, or official cardinality.
The historical count of 309 describes forum identities and discussion bindings
only. Section 20009 is enacted and mandatory. Phil/Boss has settled that
Section 70310 does not exist; do not reopen a targeted search. Section 71119
requires official-source-first binding. If a neutral exhaustive official-source
inventory produces contradictory controlling evidence, stop as
BLOCKED - DOCTRINE/EVIDENCE CONFLICT.
The clean-room sequence is:
discover and preserve authoritative official-source identity and evidence;
parse neutrally and establish reviewed official scope and legal state;
generate accessible Astro presentation from reviewed evidence;
join optional verbatim forum context and discussion only afterward; and
obtain the separately required Product, Code, Manual, and Boss approvals.
Stop if: any legacy asset is treated as presumptively reusable, forum
context determines official scope, an official locator is missing or
ambiguous, or settled doctrine conflicts with controlling evidence.
This clean room is OBBBA-specific site/adapter evidence. It does not authorize
publication, Gate 2, reusable Astro-package behavior, or portable Core adoption.
Official Text, Community Source, And Related Pages
For community-maintained legal or public-record content, show two separate
source relationships:
Content source: the protected Discourse source topic. A topic may be a
wiki, but wiki status is optional metadata rather than the ownership or
no-writeback basis.
Official text: the identified law/document and section, with its official
citation or page range.
Do not present the community wiki as the official record, and do not hide the
community source behind the official citation. For OBBBA, use Congress.gov
Public Law 119-21: its text page for overview, USLM XML for structured
matching, official TXT for page-marker/fallback evidence, and PDF for visual
verification. Use Statutes at Large pages, not PDF viewer page numbers.
Before publishing a comparison:
identify the document and structural section;
require one unambiguous official match;
compare without writing to either source;
classify the result as exact, presentation-only, substantive-difference, or
unresolved;
route substantive or unresolved results for review.
Presentation-only comparison may ignore Markdown links, wrapping/whitespace,
typographic punctuation, page furniture, and official side notes. It must not
normalize away changed words or numbering. The comparator preserves case:
capitalization-only differences are substantive and require the normal
review/explicit-override path because legal capitalization may identify defined
terms or identifiers.
Bounded evidence: OBBBA topic 34/post 40, Section 10101, matched USLM
/us/pl/119/21/tI/stA/s10101. Both normalized forms had 608 tokens and 3,148
characters with zero substantive differences. Cite Public Law 119-21,
Section 10101, 139 Stat. 80–81. This proves only that comparison.
Related pages are separate from provenance. Use a stable key such as
sectionId to connect OBBBA Text, Law as Amended, Impact, and Stories.
Generate reciprocal links during manifest generation and Astro build instead
of maintaining them in article bodies. A Story may reference multiple section
IDs, and a section may have multiple Stories.
You should see: linked Content source and Official text disclosures,
followed separately by actions such as “Read the enacted text,” “Explore the
impact,” and “View 3 community stories.”
Stop if: matching is missing, duplicated, or ambiguous; comparison would
rewrite community text; a PDF file-page number is used as the legal citation;
provenance is mixed with Related links; or adding a Story requires manually
editing every linked page.
Commit e775af3 implements strict us-public-law enrichment, source-tag
provenance, fail-closed manifest-v2 preflight, accessible reciprocal relations,
and a many-to-many Stories graph: a section can list many Stories, and a Story
can reference many sections. No-overwrite imports skip before
raw-post or official-source reads. A substantive result requires an explicit
per-entry override.
You should see in the reviewed demo: accessible source/official
provenance, reciprocal cross-lens links, and static navigation with no
build-time network requirement.
OBBBA topic 34 now renders the Content source, linked source author, official
Public Law 119-21/Title I/Section 10101 citation, Impact relation, and topic 34
discussion. Impact 10101 links back to the official-text route and retains topic
434. No Discourse writes occurred.
Still open: deployment and live acceptance of the exact reviewed
official-source OBBBA Text candidate, Law as Amended as a separate clean
official-source lane, broader scale/a11y proof, and dependency review.
If public tag-group discovery returns 429, the corrected client reads groups
sequentially and retries only 429 up to three times. It honors bounded
Retry-After seconds/date or fallback delay and cancels rejected response
bodies promptly. A 403 is not retryable; correct permissions instead.
The current reviewed OBBBA navigation artifact is
astro-discussion-bridge-0.1.0-alpha-official-nav-19f3066a.tgz (SHA256
19f3066a1affc8d835d321aa1fb91af663800d5baa57d7a9e9a811d9b43655a9).
Its 310-section official-source candidate is not yet authorized for deployment.
Readable docs display Last updated and
Applies to: DiscussionBridge Alpha directly under the page title. The
footer repeats only Last updated and provides an edit link to the exact
canonical Markdown source on GitHub.
Last updated records a verified change to that canonical source. It is not the
date of the latest docs build or deployment.
After editing any canonical file under docs/:
Terminal window
cd sites/docs
npm run refresh-metadata
npm run build
The refresh updates docs/DOCS_PAGE_METADATA.json: unchanged pages keep their
dates, changed pages receive the refresh date, new pages are initialized, and
removed pages leave the ledger. The build checks exact source coverage and
byte-level hashes before syncing content.
You should see: metadata tests 2/2, a successful readable build, the
correct title row on desktop/mobile, and an edit link resolving to the page’s
canonical source.
Stop if: metadata is missing or stale, a source hash differs, membership
is not exact, a date is inferred from Git/build/deploy time, or the edit link
points to generated content instead of the canonical source.
Metadata verification does not replace Manual Boss semantic and presentation
review.