fix(aiui): fabricated demo content is demo-build-only, fake credential scrubbed (S7)
Per operator decision 2026-08-07 (mock content is isolated to demo.archipelago-foundation.org, never in shipped code): the auto-seeded 'node-demo' conversation (invented balances, file listings, bitcoin.conf) no longer ships on nodes — a VITE_DEMO_CONTENT build flag (or dev) gates it, /seed, and the Guide 'Load Demo' button. The genuine onboarding guide still seeds everywhere. The fixture's bitcoin.conf rpcpassword is now unmistakably example-shaped: fake must never look like a real credential. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -113,7 +113,7 @@ txindex=1
|
||||
|
||||
# RPC Settings
|
||||
rpcuser=archipelago
|
||||
rpcpassword=archipelago123
|
||||
rpcpassword=EXAMPLE-ONLY-not-a-real-password
|
||||
rpcallowip=127.0.0.1
|
||||
rpcbind=127.0.0.1
|
||||
rpcport=8332
|
||||
|
||||
@@ -148,6 +148,7 @@
|
||||
import { computed, ref, watch, nextTick } from 'vue'
|
||||
import { useVirtualizer } from '@tanstack/vue-virtual'
|
||||
import { useChatStore } from '@/stores/chat'
|
||||
import { DEMO_CONTENT_ENABLED } from '@/utils/demoContent'
|
||||
import { useAI, streamWithModel } from '@/composables/useAI'
|
||||
import { useContentPanel } from '@/composables/useContentPanel'
|
||||
import { useComparisonMode } from '@/composables/useComparisonMode'
|
||||
@@ -354,6 +355,18 @@ async function handleSend(text: string, images: ImageAttachment[] = []) {
|
||||
}
|
||||
|
||||
if (trimmed === '/seed') {
|
||||
// Demo-site/dev only (S7): the seed showcase is fabricated example
|
||||
// content and must not ship in the node build.
|
||||
if (!DEMO_CONTENT_ENABLED) {
|
||||
const convId = chatStore.activeConversationId
|
||||
if (convId) {
|
||||
chatStore.addMessage(convId, {
|
||||
role: 'assistant',
|
||||
content: 'The `/seed` showcase is only available in demo builds.',
|
||||
})
|
||||
}
|
||||
return
|
||||
}
|
||||
await chatStore.loadSeedChats()
|
||||
// loadSeedChats already switches to the seed conversation
|
||||
// Collapse chat so user sees PromptIndex for quick picking
|
||||
|
||||
@@ -86,6 +86,7 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, watch } from 'vue'
|
||||
import { usePromptTemplateStore, extractVariables, type PromptTemplate } from '@/stores/promptTemplates'
|
||||
import { DEMO_CONTENT_ENABLED } from '@/utils/demoContent'
|
||||
|
||||
interface PaletteCommand {
|
||||
id: string
|
||||
@@ -99,7 +100,10 @@ const BUILT_IN_COMMANDS: PaletteCommand[] = [
|
||||
{ id: 'cmd-nostr', slash: '/nostr', title: 'Nostr', preview: 'Browse the Nostr network feed' },
|
||||
{ id: 'cmd-design', slash: '/design', title: 'Design System', preview: 'Open the design system viewer' },
|
||||
{ id: 'cmd-search', slash: '/search ', title: 'Search', preview: 'Search your content library' },
|
||||
{ id: 'cmd-seed', slash: '/seed', title: 'Seed', preview: 'Load seed conversations for all content types' },
|
||||
// /seed loads fabricated showcase content — demo-site/dev builds only (S7)
|
||||
...(DEMO_CONTENT_ENABLED
|
||||
? [{ id: 'cmd-seed', slash: '/seed', title: 'Seed', preview: 'Load seed conversations for all content types' }]
|
||||
: []),
|
||||
{ id: 'cmd-freefilms', slash: '/freefilms', title: 'Free Films', preview: 'Browse free documentary films from InDeeHub' },
|
||||
]
|
||||
|
||||
|
||||
@@ -197,8 +197,9 @@
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<!-- Try It -->
|
||||
<section class="guide-section">
|
||||
<!-- Try It — demo builds only (S7): the demo conversation is
|
||||
fabricated example node state, demo-site/dev only -->
|
||||
<section v-if="DEMO_CONTENT_ENABLED" class="guide-section">
|
||||
<h2 class="section-title">
|
||||
<span class="section-icon">🚀</span>
|
||||
Try It Out
|
||||
@@ -220,6 +221,7 @@
|
||||
import { ref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useChatStore } from '@/stores/chat'
|
||||
import { DEMO_CONTENT_ENABLED } from '@/utils/demoContent'
|
||||
|
||||
const router = useRouter()
|
||||
const chatStore = useChatStore()
|
||||
|
||||
@@ -2,6 +2,7 @@ import { defineStore } from 'pinia'
|
||||
import { ref, computed, watch } from 'vue'
|
||||
import type { Message, Conversation, WebSearchResult } from '@aiui/core/types/message'
|
||||
import { apiFetch } from '@/utils/api-fetch'
|
||||
import { DEMO_CONTENT_ENABLED } from '@/utils/demoContent'
|
||||
|
||||
function generateId(): string {
|
||||
if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
|
||||
@@ -406,8 +407,9 @@ export const useChatStore = defineStore('chat', () => {
|
||||
return siblings
|
||||
}
|
||||
|
||||
/** Load all seed prompts as a single conversation */
|
||||
/** Load all seed prompts as a single conversation — demo builds only (S7) */
|
||||
async function loadSeedChats(): Promise<number> {
|
||||
if (!DEMO_CONTENT_ENABLED) return 0
|
||||
try {
|
||||
const { seedPromptsToConversation } = await import('@/__tests__/fixtures/seedPrompts')
|
||||
const conv = seedPromptsToConversation() as Conversation
|
||||
@@ -429,8 +431,10 @@ export const useChatStore = defineStore('chat', () => {
|
||||
}
|
||||
}
|
||||
|
||||
/** Load node demo conversation showing local node capabilities */
|
||||
/** Load node demo conversation — demo builds only (S7); the content is
|
||||
* fabricated node state and must not ship on real nodes */
|
||||
async function loadNodeDemoChat(): Promise<number> {
|
||||
if (!DEMO_CONTENT_ENABLED) return 0
|
||||
try {
|
||||
const { nodeDemoToConversation } = await import('@/__tests__/fixtures/nodeDemoPrompts')
|
||||
const conv = nodeDemoToConversation() as Conversation
|
||||
@@ -472,11 +476,16 @@ export const useChatStore = defineStore('chat', () => {
|
||||
}
|
||||
}
|
||||
|
||||
/** Seed demo conversations (guide + node demo) on first use */
|
||||
/** Seed demo conversations (guide always; node demo only in demo builds) */
|
||||
async function seedDemoConversations(): Promise<void> {
|
||||
// The guide is genuine onboarding documentation — always seed it.
|
||||
// `node-demo` is FABRICATED node state (invented balances, file listings,
|
||||
// a fake bitcoin.conf) — demo-site/dev builds only (S7, operator
|
||||
// decision 2026-08-07: mocks belong to the demo site, not shipped code).
|
||||
const wantDemo = DEMO_CONTENT_ENABLED
|
||||
const hasGuide = conversations.value.has('aiui-guide')
|
||||
const hasDemo = conversations.value.has('node-demo')
|
||||
if (hasGuide && hasDemo) {
|
||||
if (hasGuide && (hasDemo || !wantDemo)) {
|
||||
// Already seeded — still select guide if nothing active
|
||||
if (!activeConversationId.value) {
|
||||
activeConversationId.value = 'aiui-guide'
|
||||
@@ -485,15 +494,15 @@ export const useChatStore = defineStore('chat', () => {
|
||||
}
|
||||
try {
|
||||
const { guideToConversation } = await import('@/__tests__/fixtures/guideConversation')
|
||||
const { nodeDemoToConversation } = await import('@/__tests__/fixtures/nodeDemoPrompts')
|
||||
const guide = guideToConversation() as Conversation
|
||||
const demo = nodeDemoToConversation() as Conversation
|
||||
const merged = new Map(conversations.value)
|
||||
if (!merged.has(guide.id)) {
|
||||
merged.set(guide.id, guide)
|
||||
immediateIDBSave(guide)
|
||||
}
|
||||
if (!merged.has(demo.id)) {
|
||||
if (wantDemo && !merged.has('node-demo')) {
|
||||
const { nodeDemoToConversation } = await import('@/__tests__/fixtures/nodeDemoPrompts')
|
||||
const demo = nodeDemoToConversation() as Conversation
|
||||
merged.set(demo.id, demo)
|
||||
immediateIDBSave(demo)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* Demo-content gate (operator decision 2026-08-07): seed/mock showcase
|
||||
* conversations exist for the demo.archipelago-foundation.org website ONLY
|
||||
* and must not ship in the node build. Demo builds set
|
||||
* `VITE_DEMO_CONTENT=true`; local dev keeps them for development.
|
||||
*
|
||||
* Anything behind this flag is fabricated example content — never present
|
||||
* it as real node data in a shipped build.
|
||||
*/
|
||||
export const DEMO_CONTENT_ENABLED =
|
||||
import.meta.env.DEV || import.meta.env.VITE_DEMO_CONTENT === 'true'
|
||||
Reference in New Issue
Block a user