Add plans audit: status overview + fragment protocol, glue decoupling, social sharing pages

Audit all plan files and create documentation pages for what remains:
- Status overview with green/amber/stone badges for all 15 plans
- Fragment Protocol: what exists (GET), what remains (POST sexp, structured response)
- Glue Decoupling: 25+ cross-app imports to eliminate via glue service layer
- Social Sharing: 6-phase OAuth-based sharing to major platforms

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-07 08:35:27 +00:00
parent 6215d3573b
commit feb368f7fb
3 changed files with 290 additions and 1 deletions

View File

@@ -109,10 +109,18 @@
(dict :label "Routing Analyzer" :href "/isomorphism/routing-analyzer")))
(define plans-nav-items (list
(dict :label "Status" :href "/plans/status"
:summary "Audit of all plans — what's done, what's in progress, and what remains.")
(dict :label "Reader Macros" :href "/plans/reader-macros"
:summary "Extensible parse-time transformations via # dispatch — datum comments, raw strings, and quote shorthand.")
(dict :label "SX-Activity" :href "/plans/sx-activity"
:summary "A new web built on SX — executable content, shared components, parsers, and logic on IPFS, provenance on Bitcoin, all running within your own security context.")))
:summary "A new web built on SX — executable content, shared components, parsers, and logic on IPFS, provenance on Bitcoin, all running within your own security context.")
(dict :label "Fragment Protocol" :href "/plans/fragment-protocol"
:summary "Structured sexp request/response for cross-service component transfer.")
(dict :label "Glue Decoupling" :href "/plans/glue-decoupling"
:summary "Eliminate all cross-app model imports via glue service layer.")
(dict :label "Social Sharing" :href "/plans/social-sharing"
:summary "OAuth-based sharing to Facebook, Instagram, Threads, Twitter/X, LinkedIn, and Mastodon.")))
(define bootstrappers-nav-items (list
(dict :label "Overview" :href "/bootstrappers/")

View File

@@ -594,6 +594,283 @@
(td :class "px-3 py-2 text-stone-700" "Content addressing — shared with component CIDs")
(td :class "px-3 py-2 text-stone-600" "2, 3"))))))))
;; ---------------------------------------------------------------------------
;; Plan Status Overview
;; ---------------------------------------------------------------------------
(defcomp ~plan-status-content ()
(~doc-page :title "Plan Status"
(p :class "text-lg text-stone-600 mb-6"
"Audit of all plans across the SX language and Rose Ash platform. Last updated March 2026.")
;; -----------------------------------------------------------------------
;; Completed
;; -----------------------------------------------------------------------
(~doc-section :title "Completed" :id "completed"
(div :class "space-y-4"
(div :class "rounded border border-green-200 bg-green-50 p-4"
(div :class "flex items-center gap-2 mb-1"
(span :class "inline-block px-2 py-0.5 rounded text-xs font-bold bg-green-600 text-white uppercase" "Complete")
(span :class "font-semibold text-stone-800" "Split Cart into Microservices"))
(p :class "text-sm text-stone-600" "Cart decomposed into 4 services: relations (internal, owns ContainerRelation), likes (internal, unified generic likes), orders (public, owns Order/OrderItem + SumUp checkout), and cart (thin CartItem CRUD). All three new services deployed with dedicated databases."))
(div :class "rounded border border-green-200 bg-green-50 p-4"
(div :class "flex items-center gap-2 mb-1"
(span :class "inline-block px-2 py-0.5 rounded text-xs font-bold bg-green-600 text-white uppercase" "Complete")
(span :class "font-semibold text-stone-800" "Ticket Purchase Through Cart"))
(p :class "text-sm text-stone-600" "Tickets flow through the cart like products: state=pending in cart, reserved at checkout, confirmed on payment. TicketDTO, CartSummaryDTO with ticket_count/ticket_total, CalendarService protocol methods all implemented."))
(div :class "rounded border border-green-200 bg-green-50 p-4"
(div :class "flex items-center gap-2 mb-1"
(span :class "inline-block px-2 py-0.5 rounded text-xs font-bold bg-green-600 text-white uppercase" "Complete")
(span :class "font-semibold text-stone-800" "Ticket UX Improvements"))
(p :class "text-sm text-stone-600" "+/- quantity buttons on entry pages and cart. Tickets grouped by event in cart display. Adjust quantity route, sold/basket counts, matching product card UX pattern."))
(div :class "rounded border border-green-200 bg-green-50 p-4"
(div :class "flex items-center gap-2 mb-1"
(span :class "inline-block px-2 py-0.5 rounded text-xs font-bold bg-green-600 text-white uppercase" "Complete")
(a :href "/isomorphism/" :class "font-semibold text-green-800 underline" "Isomorphic Phase 1: Dependency Analysis"))
(p :class "text-sm text-stone-600" "Per-page component bundles via deps.sx. Transitive closure, scan-refs, components-needed, page-css-classes. 15 tests, bootstrapped to both hosts."))
(div :class "rounded border border-green-200 bg-green-50 p-4"
(div :class "flex items-center gap-2 mb-1"
(span :class "inline-block px-2 py-0.5 rounded text-xs font-bold bg-green-600 text-white uppercase" "Complete")
(a :href "/isomorphism/" :class "font-semibold text-green-800 underline" "Isomorphic Phase 2: IO Detection"))
(p :class "text-sm text-stone-600" "Automatic IO classification. scan-io-refs, transitive-io-refs, compute-all-io-refs. Server expands IO components, serializes pure ones for client."))
(div :class "rounded border border-green-200 bg-green-50 p-4"
(div :class "flex items-center gap-2 mb-1"
(span :class "inline-block px-2 py-0.5 rounded text-xs font-bold bg-green-600 text-white uppercase" "Complete")
(a :href "/isomorphism/" :class "font-semibold text-green-800 underline" "Isomorphic Phase 3: Client-Side Routing"))
(p :class "text-sm text-stone-600" "router.sx spec, page registry via <script type=\"text/sx-pages\">, client route matching, try-first/fallback to server. Pure pages render without server roundtrips."))))
;; -----------------------------------------------------------------------
;; In Progress / Partial
;; -----------------------------------------------------------------------
(~doc-section :title "In Progress" :id "in-progress"
(div :class "space-y-4"
(div :class "rounded border border-amber-200 bg-amber-50 p-4"
(div :class "flex items-center gap-2 mb-1"
(span :class "inline-block px-2 py-0.5 rounded text-xs font-bold bg-amber-600 text-white uppercase" "Partial")
(a :href "/plans/fragment-protocol" :class "font-semibold text-amber-900 underline" "Fragment Protocol"))
(p :class "text-sm text-stone-600" "Fragment GET infrastructure works. The planned POST/sexp structured protocol for transferring component definitions between services is not yet implemented. Fragment endpoints still use legacy GET + X-Fragment-Request headers."))
(div :class "rounded border border-amber-200 bg-amber-50 p-4"
(div :class "flex items-center gap-2 mb-1"
(span :class "inline-block px-2 py-0.5 rounded text-xs font-bold bg-amber-600 text-white uppercase" "Partial")
(a :href "/isomorphism/" :class "font-semibold text-amber-900 underline" "Isomorphic Phase 4: Client Async & IO Bridge"))
(p :class "text-sm text-stone-600" "Some async evaluation infrastructure exists (helpers.py, async_eval.py). The io-bridge.sx spec file for client-side IO primitives (query -> REST, frag -> fetch) does not exist yet."))))
;; -----------------------------------------------------------------------
;; Not Started
;; -----------------------------------------------------------------------
(~doc-section :title "Not Started" :id "not-started"
(div :class "space-y-4"
(div :class "rounded border border-stone-200 bg-stone-50 p-4"
(div :class "flex items-center gap-2 mb-1"
(span :class "inline-block px-2 py-0.5 rounded text-xs font-bold bg-stone-500 text-white uppercase" "Not Started")
(a :href "/plans/reader-macros" :class "font-semibold text-stone-800 underline" "Reader Macros"))
(p :class "text-sm text-stone-600" "# dispatch character for datum comments (#;), raw strings (#|...|), and quote shorthand (#'). Fully designed but no implementation in parser.sx or parser.py.")
(p :class "text-sm text-stone-500 mt-1" "Remaining: spec in parser.sx, Python in parser.py, rebootstrap both targets."))
(div :class "rounded border border-stone-200 bg-stone-50 p-4"
(div :class "flex items-center gap-2 mb-1"
(span :class "inline-block px-2 py-0.5 rounded text-xs font-bold bg-stone-500 text-white uppercase" "Not Started")
(a :href "/plans/sx-activity" :class "font-semibold text-stone-800 underline" "SX-Activity"))
(p :class "text-sm text-stone-600" "Federated SX over ActivityPub — 6 phases from SX wire format for activities to the evaluable web on IPFS. Existing AP infrastructure provides the foundation but no SX-specific federation code exists.")
(p :class "text-sm text-stone-500 mt-1" "Remaining: shared/sx/activity.py (SX<->JSON-LD), shared/sx/ipfs.py, shared/sx/ref/ipfs-resolve.sx, shared/sx/registry.py, shared/sx/anchor.py."))
(div :class "rounded border border-stone-200 bg-stone-50 p-4"
(div :class "flex items-center gap-2 mb-1"
(span :class "inline-block px-2 py-0.5 rounded text-xs font-bold bg-stone-500 text-white uppercase" "Not Started")
(a :href "/plans/glue-decoupling" :class "font-semibold text-stone-800 underline" "Cross-App Decoupling via Glue"))
(p :class "text-sm text-stone-600" "Eliminate all cross-app model imports by routing through a glue service layer. No glue/ directory exists. Apps are currently decoupled via HTTP interfaces and DTOs instead.")
(p :class "text-sm text-stone-500 mt-1" "Remaining: glue/services/ for pages, page_config, calendars, marketplaces, cart_items, products, post_associations. 25+ cross-app imports to eliminate."))
(div :class "rounded border border-stone-200 bg-stone-50 p-4"
(div :class "flex items-center gap-2 mb-1"
(span :class "inline-block px-2 py-0.5 rounded text-xs font-bold bg-stone-500 text-white uppercase" "Not Started")
(a :href "/plans/social-sharing" :class "font-semibold text-stone-800 underline" "Social Network Sharing"))
(p :class "text-sm text-stone-600" "OAuth-based sharing to Facebook, Instagram, Threads, Twitter/X, LinkedIn, and Mastodon via the account service. No models, blueprints, or platform clients created.")
(p :class "text-sm text-stone-500 mt-1" "Remaining: SocialConnection model, social_crypto.py, platform OAuth clients (6), account/bp/social/ blueprint, share button fragment."))
(div :class "rounded border border-stone-200 bg-stone-50 p-4"
(div :class "flex items-center gap-2 mb-1"
(span :class "inline-block px-2 py-0.5 rounded text-xs font-bold bg-stone-500 text-white uppercase" "Not Started")
(a :href "/isomorphism/" :class "font-semibold text-stone-800 underline" "Isomorphic Phase 5: Streaming & Suspense"))
(p :class "text-sm text-stone-600" "Server streams partially-evaluated SX as IO resolves. Client renders available subtrees immediately, fills in suspended parts. No suspense.sx spec or chunked transfer implementation.")
(p :class "text-sm text-stone-500 mt-1" "Depends on: Phase 4 (client async)."))
(div :class "rounded border border-stone-200 bg-stone-50 p-4"
(div :class "flex items-center gap-2 mb-1"
(span :class "inline-block px-2 py-0.5 rounded text-xs font-bold bg-stone-500 text-white uppercase" "Not Started")
(a :href "/isomorphism/" :class "font-semibold text-stone-800 underline" "Isomorphic Phase 6: Full Isomorphism"))
(p :class "text-sm text-stone-600" "Runtime boundary optimizer, affinity annotations, offline data layer via Service Worker + IndexedDB, isomorphic testing harness.")
(p :class "text-sm text-stone-500 mt-1" "Depends on: all previous phases."))))))
;; ---------------------------------------------------------------------------
;; Fragment Protocol
;; ---------------------------------------------------------------------------
(defcomp ~plan-fragment-protocol-content ()
(~doc-page :title "Fragment Protocol"
(~doc-section :title "Context" :id "context"
(p "Fragment endpoints return raw sexp source (e.g., " (code "(~blog-nav-wrapper :items ...)") "). The consuming service embeds this in its page sexp, which the client evaluates. But service-specific components like " (code "~blog-nav-wrapper") " are only in that service's component env — not in the consumer's. So the consumer's " (code "client_components_tag()") " never sends them to the client, causing \"Unknown component\" errors.")
(p "The fix: transfer component definitions alongside fragments. Services tell the provider what they already have; the provider sends only what's missing."))
(~doc-section :title "What exists" :id "exists"
(div :class "rounded border border-green-200 bg-green-50 p-4"
(ul :class "list-disc pl-5 text-stone-700 space-y-1"
(li "Fragment GET infrastructure works (" (code "shared/infrastructure/fragments.py") ")")
(li (code "X-Fragment-Request") " header protocol for internal service calls")
(li "Content type negotiation for text/html and text/sx responses")
(li "Fragment caching and composition in page rendering"))))
(~doc-section :title "What remains" :id "remains"
(div :class "rounded border border-amber-200 bg-amber-50 p-4"
(ul :class "list-disc pl-5 text-stone-700 space-y-1"
(li (strong "POST sexp protocol: ") "Switch from GET to POST with structured sexp body containing " (code ":components") " list of what consumer already has")
(li (strong "Structured response: ") (code "(fragment-response :defs (...) :content (...))") " — provider sends only missing component defs")
(li (strong (code "fragment_response()") " builder: ") "New function in helpers.py that diffs provider's component env against consumer's list")
(li (strong "Register received defs: ") "Consumer parses " (code ":defs") " from response and registers into its " (code "_COMPONENT_ENV"))
(li (strong "Shared blueprint factory: ") (code "create_fragment_blueprint(handlers)") " to deduplicate the identical fragment endpoint pattern across 8 services"))))
(~doc-section :title "Files to modify" :id "files"
(div :class "overflow-x-auto rounded border border-stone-200"
(table :class "w-full text-left text-sm"
(thead (tr :class "border-b border-stone-200 bg-stone-100"
(th :class "px-3 py-2 font-medium text-stone-600" "File")
(th :class "px-3 py-2 font-medium text-stone-600" "Change")))
(tbody
(tr :class "border-b border-stone-100"
(td :class "px-3 py-2 font-mono text-sm text-violet-700" "shared/infrastructure/fragments.py")
(td :class "px-3 py-2 text-stone-700" "POST sexp body, parse response, register defs"))
(tr :class "border-b border-stone-100"
(td :class "px-3 py-2 font-mono text-sm text-violet-700" "shared/sx/helpers.py")
(td :class "px-3 py-2 text-stone-700" "fragment_response() builder"))
(tr :class "border-b border-stone-100"
(td :class "px-3 py-2 font-mono text-sm text-violet-700" "shared/infrastructure/fragment_endpoint.py")
(td :class "px-3 py-2 text-stone-700" "NEW — shared blueprint factory"))
(tr :class "border-b border-stone-100"
(td :class "px-3 py-2 font-mono text-sm text-violet-700" "*/bp/fragments/routes.py")
(td :class "px-3 py-2 text-stone-700" "All 8 services: use create_fragment_blueprint"))))))))
;; ---------------------------------------------------------------------------
;; Glue Decoupling
;; ---------------------------------------------------------------------------
(defcomp ~plan-glue-decoupling-content ()
(~doc-page :title "Cross-App Decoupling via Glue Services"
(~doc-section :title "Context" :id "context"
(p "All cross-domain FK constraints have been dropped (with pragmatic exceptions for OrderItem.product_id and CartItem). Cross-domain writes go through internal HTTP and activity bus. However, " (strong "25+ cross-app model imports remain") " — apps still import from each other's models/ directories. This means every app needs every other app's code on disk to start.")
(p "The goal: eliminate all cross-app model imports. Every app only imports from its own models/, from shared/, and from a new glue/ service layer."))
(~doc-section :title "Current state" :id "current"
(p "Apps are partially decoupled via HTTP interfaces (fetch_data, call_action, send_internal_activity) and DTOs. The Cart microservice split (relations, likes, orders) is complete. But direct model imports persist in:")
(ul :class "list-disc pl-5 text-stone-700 space-y-1"
(li (strong "Cart") " — 9 files importing from market, events, blog")
(li (strong "Blog") " — 8 files importing from cart, events, market")
(li (strong "Events") " — 5 files importing from blog, market, cart")
(li (strong "Market") " — 1 file importing from blog")))
(~doc-section :title "What remains" :id "remains"
(div :class "space-y-3"
(div :class "rounded border border-stone-200 p-3"
(h4 :class "font-semibold text-stone-700" "1. glue/services/pages.py")
(p :class "text-sm text-stone-600" "Dict-based Post access for non-blog apps: get_page_by_slug, get_page_by_id, get_pages_by_ids, page_exists, search_posts."))
(div :class "rounded border border-stone-200 p-3"
(h4 :class "font-semibold text-stone-700" "2. glue/services/page_config.py")
(p :class "text-sm text-stone-600" "PageConfig CRUD: get_page_config, get_or_create_page_config, get_page_configs_by_ids."))
(div :class "rounded border border-stone-200 p-3"
(h4 :class "font-semibold text-stone-700" "3. glue/services/calendars.py")
(p :class "text-sm text-stone-600" "Calendar queries + entry associations (from blog): get_calendars_for_page, toggle_entry_association, get_associated_entries."))
(div :class "rounded border border-stone-200 p-3"
(h4 :class "font-semibold text-stone-700" "4. glue/services/marketplaces.py")
(p :class "text-sm text-stone-600" "MarketPlace CRUD (from blog+events): get_marketplaces_for_page, create_marketplace, soft_delete_marketplace."))
(div :class "rounded border border-stone-200 p-3"
(h4 :class "font-semibold text-stone-700" "5. glue/services/cart_items.py")
(p :class "text-sm text-stone-600" "CartItem/CalendarEntry queries for cart: get_cart_items, find_or_create_cart_item, clear_cart_for_order."))
(div :class "rounded border border-stone-200 p-3"
(h4 :class "font-semibold text-stone-700" "6. glue/services/products.py")
(p :class "text-sm text-stone-600" "Minimal Product access for cart orders: get_product."))
(div :class "rounded border border-stone-200 p-3"
(h4 :class "font-semibold text-stone-700" "7. Model registration + cleanup")
(p :class "text-sm text-stone-600" "register_models() in glue/setup.py, update all app.py files, delete moved service files."))))
(~doc-section :title "Docker consideration" :id "docker"
(p :class "text-stone-600" "For glue services to work in Docker (single app per container), model files from other apps must be importable. Recommended: try/except at import time — glue services that can't import a model raise ImportError at call time, which only happens if called from the wrong app."))))
;; ---------------------------------------------------------------------------
;; Social Sharing
;; ---------------------------------------------------------------------------
(defcomp ~plan-social-sharing-content ()
(~doc-page :title "Social Network Sharing"
(~doc-section :title "Context" :id "context"
(p "Rose Ash already has ActivityPub for federated social sharing. This plan adds OAuth-based sharing to mainstream social networks — Facebook, Instagram, Threads, Twitter/X, LinkedIn, and Mastodon.")
(p "All social logic lives in the " (strong "account") " microservice. Content apps get a share button that opens the account share page."))
(~doc-section :title "What remains" :id "remains"
(~doc-note "Nothing has been implemented. This is the full scope of work.")
(div :class "space-y-4"
(div :class "rounded border border-stone-200 p-4"
(h4 :class "font-semibold text-stone-700 mb-2" "Phase 1: Data Model + Encryption")
(ul :class "list-disc pl-5 text-stone-700 space-y-1 text-sm"
(li (code "shared/models/social_connection.py") " — SocialConnection model (user_id, platform, tokens, scopes, extra_data)")
(li (code "shared/infrastructure/social_crypto.py") " — Fernet encrypt/decrypt for tokens")
(li "Alembic migration for social_connections table")
(li "Environment variables for per-platform OAuth credentials")))
(div :class "rounded border border-stone-200 p-4"
(h4 :class "font-semibold text-stone-700 mb-2" "Phase 2: Platform OAuth Clients")
(p :class "text-sm text-stone-600 mb-2" "All in " (code "account/services/social_platforms/") ":")
(ul :class "list-disc pl-5 text-stone-700 space-y-1 text-sm"
(li (code "base.py") " — SocialPlatform ABC, OAuthResult, ShareResult")
(li (code "meta.py") " — Facebook + Instagram + Threads (Graph API)")
(li (code "twitter.py") " — OAuth 2.0 with PKCE")
(li (code "linkedin.py") " — LinkedIn Posts API")
(li (code "mastodon.py") " — Dynamic app registration per instance")))
(div :class "rounded border border-stone-200 p-4"
(h4 :class "font-semibold text-stone-700 mb-2" "Phase 3: Account Blueprint")
(ul :class "list-disc pl-5 text-stone-700 space-y-1 text-sm"
(li (code "account/bp/social/routes.py") " — /social/ list, /social/connect/<platform>/, /social/callback/<platform>/, /social/share/")
(li "Register before account blueprint (account has catch-all /<slug>/ route)")))
(div :class "rounded border border-stone-200 p-4"
(h4 :class "font-semibold text-stone-700 mb-2" "Phase 4: Templates")
(ul :class "list-disc pl-5 text-stone-700 space-y-1 text-sm"
(li "Social panel — platform cards, connect/disconnect")
(li "Share panel — content preview, account checkboxes, share button")
(li "Share result — per-platform success/failure with links")))
(div :class "rounded border border-stone-200 p-4"
(h4 :class "font-semibold text-stone-700 mb-2" "Phase 5: Share Button in Content Apps")
(ul :class "list-disc pl-5 text-stone-700 space-y-1 text-sm"
(li "share-button fragment from account service")
(li "Blog, events, market detail pages fetch and render the fragment")))
(div :class "rounded border border-stone-200 p-4"
(h4 :class "font-semibold text-stone-700 mb-2" "Phase 6: Token Refresh + Share History")
(ul :class "list-disc pl-5 text-stone-700 space-y-1 text-sm"
(li "Automatic token refresh before posting")
(li "Optional social_shares table for history and duplicate prevention")))))))
;; ---------------------------------------------------------------------------
;; Isomorphic Architecture Roadmap
;; ---------------------------------------------------------------------------

View File

@@ -475,6 +475,10 @@
:current (find-current plans-nav-items slug))
:selected (or (find-current plans-nav-items slug) ""))
:content (case slug
"status" (~plan-status-content)
"reader-macros" (~plan-reader-macros-content)
"sx-activity" (~plan-sx-activity-content)
"fragment-protocol" (~plan-fragment-protocol-content)
"glue-decoupling" (~plan-glue-decoupling-content)
"social-sharing" (~plan-social-sharing-content)
:else (~plans-index-content)))