{
  "@context": [
    "https://linkedsoftwaredependencies.org/bundles/npm/@solid/community-server/^8.0.0/components/context.jsonld",
    "https://linkedsoftwaredependencies.org/bundles/npm/@undefineds.co/xpod/^0.0.0/components/context.jsonld",
    "https://linkedsoftwaredependencies.org/bundles/npm/asynchronous-handlers/^1.0.0/components/context.jsonld"
  ],
  "import": [
    "./main.json",
    "./xpod.base.json",
    "./terminal.json",
    "./extensions.local.initializer.json"
  ],
  "@graph": [
    {
      "comment": "Quota service backed by identity DB, no env defaults = unlimited",
      "@id": "urn:undefineds:xpod:QuotaService",
      "@type": "DrizzleQuotaService",
      "DrizzleQuotaService:_options_identityDbUrl": {
        "@id": "urn:solid-server:default:variable:identityDbUrl",
        "@type": "Variable"
      }
    },
    {
      "comment": "定义 oidcIssuer 变量（外部 OIDC issuer 基础 URL），设置后本地仍提供 account/consent/SP 页面",
      "@id": "urn:solid-server:default:variable:oidcIssuer",
      "@type": "Variable"
    },
    {
      "comment": "Auto-detect OIDC pass-through - 有 oidcIssuer 时也保持本地 CSS OIDC discovery/token/JWKS 同源",
      "@id": "urn:undefineds:xpod:AutoDetectOidcHandler",
      "@type": "AutoDetectOidcHandler",
      "AutoDetectOidcHandler:_options_oidcIssuer": {
        "@id": "urn:solid-server:default:variable:oidcIssuer"
      },
      "AutoDetectOidcHandler:_options_cacheMs": 300000
    },
    {
      "comment": "CSS 原生 IdentityProvider parsing handler，始终用于本地 account/consent/WebID 选择页面",
      "@id": "urn:undefineds:xpod:SourceIdentityProviderHandler",
      "@type": "RouterHandler",
      "baseUrl": {
        "@id": "urn:solid-server:default:variable:baseUrl"
      },
      "targetExtractor": {
        "@id": "urn:solid-server:default:TargetExtractor"
      },
      "allowedPathNames": [
        "^/.account(/.*)?$"
      ],
      "handler": {
        "@id": "urn:solid-server:default:IdentityProviderParsingHandler"
      }
    },
    {
      "comment": "Auto-detect Identity Provider Handler - 有 oidcIssuer 时仍委托本地 account/consent，避免 Local 登录漏到 Cloud Pod",
      "@id": "urn:undefineds:xpod:AutoDetectIdentityProviderHandler",
      "@type": "AutoDetectIdentityProviderHandler",
      "AutoDetectIdentityProviderHandler:_options_oidcIssuer": {
        "@id": "urn:solid-server:default:variable:oidcIssuer"
      },
      "AutoDetectIdentityProviderHandler:_options_source": {
        "@id": "urn:undefineds:xpod:SourceIdentityProviderHandler"
      }
    },
    {
      "comment": "Override: 使用 AutoDetectIdentityProviderHandler 替换默认 Handler",
      "@type": "Override",
      "overrideInstance": {
        "@id": "urn:solid-server:default:IdentityProviderHandler"
      },
      "overrideParameters": {
        "@id": "urn:undefineds:xpod:AutoDetectIdentityProviderHandler"
      }
    },
    {
      "comment": "Recover the local RDF authority journal after primary initialization and before workers start.",
      "@id": "urn:solid-server:default:PrimarySequenceInitializer",
      "@type": "SequenceHandler",
      "handlers": [
        { "@id": "urn:solid-server:default:CleanupInitializer" },
        { "@id": "urn:solid-server:default:MigrationInitializer" },
        { "@id": "urn:solid-server:default:BaseUrlVerifier" },
        { "@id": "urn:solid-server:default:PrimaryParallelInitializer" },
        { "@id": "urn:solid-server:default:ModuleVersionVerifier" },
        { "@id": "urn:undefineds:xpod:LocalRdfAuthorityRecoveryInitializer" },
        { "@id": "urn:solid-server:default:WorkerManager" },
        { "@id": "urn:solid-server:default:SeededAccountInitializer" },
        { "@id": "urn:undefineds:xpod:EdgeNodeAgentInitializer" }
      ]
    },
    {
      "comment": "Persistent outbox for Local authority-file writes and startup recovery.",
      "@id": "urn:undefineds:xpod:LocalRdfAuthorityJournal",
      "@type": "RootedSolidFsSyncJournal",
      "rootFilePath": {
        "@id": "urn:solid-server:default:variable:rootFilePath",
        "@type": "Variable"
      }
    },
    {
      "comment": "Rebuild the derived Local RDF index before CSS workers start.",
      "@id": "urn:undefineds:xpod:LocalRdfAuthorityRecoveryInitializer",
      "@type": "LocalRdfAuthorityRecoveryInitializer",
      "journal": {
        "@id": "urn:undefineds:xpod:LocalRdfAuthorityJournal"
      },
      "index": {
        "@id": "urn:undefineds:xpod:MixDataAccessor"
      },
      "resourceMapper": {
        "@id": "urn:solid-server:default:FileIdentifierMapper"
      },
      "baseUrl": {
        "@id": "urn:solid-server:default:variable:baseUrl",
        "@type": "Variable"
      },
      "rootFilePath": {
        "@id": "urn:solid-server:default:variable:rootFilePath",
        "@type": "Variable"
      }
    },
    {
      "@id": "urn:solid-server:default:CleanupFinalizer",
      "@type": "SequenceHandler",
      "handlers": [
        {
          "@type": "FinalizableHandler",
          "finalizable": {
            "@id": "urn:undefineds:xpod:LocalRdfAuthorityRecoveryInitializer"
          }
        }
      ]
    },
    {
      "@id": "urn:solid-server:default:variable:rootFilePath",
      "@value": "./data"
    },
    {
      "comment": "Vector API storage sharing the canonical Local RDF SQLite file.",
      "@id": "urn:undefineds:xpod:VectorStore",
      "@type": "SqliteVectorStore",
      "options_connectionString": {
        "@id": "urn:solid-server:default:variable:rdfIndexPath",
        "@type": "Variable"
      }
    },
    {
      "comment": "Vector HTTP Handler",
      "@id": "urn:undefineds:xpod:VectorHttpHandler",
      "@type": "VectorHttpHandler",
      "vectorStore": {
        "@id": "urn:undefineds:xpod:VectorStore"
      },
      "credentialsExtractor": {
        "@id": "urn:solid-server:default:CredentialsExtractor"
      },
      "permissionReader": {
        "@id": "urn:solid-server:default:PermissionReader"
      },
      "authorizer": {
        "@id": "urn:solid-server:default:Authorizer"
      }
    },
    {
      "comment": "Local FTS index sharing the canonical RDF SQLite file.",
      "@id": "urn:undefineds:xpod:RdfTextIndex",
      "@type": "RdfTextIndex",
      "options_path": {
        "@id": "urn:solid-server:default:variable:rdfIndexPath",
        "@type": "Variable"
      }
    },
    {
      "comment": "Local vector index sharing the canonical RDF SQLite file.",
      "@id": "urn:undefineds:xpod:RdfVectorIndex",
      "@type": "RdfVectorIndex",
      "options_path": {
        "@id": "urn:solid-server:default:variable:rdfIndexPath",
        "@type": "Variable"
      },
      "options_defaultMetric": "cosine"
    },
    {
      "comment": "Persistent native-only QLever process backed by the canonical RDF SQLite file.",
      "@id": "urn:undefineds:xpod:LocalQleverNativeSparqlClient",
      "@type": "LocalQleverNativeSparqlClient",
      "options_args": [
        "--sqlite-path",
        {
          "@id": "urn:solid-server:default:variable:rdfIndexPath",
          "@type": "Variable"
        }
      ]
    },
    {
      "comment": "RDF facts, FTS, VEC, and native QLever share one Local SQLite file.",
      "@id": "urn:undefineds:xpod:SolidRdfEngine",
      "@type": "SolidRdfEngine",
      "index_path": {
        "@id": "urn:solid-server:default:variable:rdfIndexPath",
        "@type": "Variable"
      },
      "textIndex": {
        "@id": "urn:undefineds:xpod:RdfTextIndex"
      },
      "vectorIndex": {
        "@id": "urn:undefineds:xpod:RdfVectorIndex"
      },
      "nativeSparqlClient": {
        "@id": "urn:undefineds:xpod:LocalQleverNativeSparqlClient"
      },
      "autoOpen": true
    },
    {
      "comment": "Default SPARQL engine: every server-owned Pod query requires native QLever.",
      "@id": "urn:undefineds:xpod:DefaultSparqlEngine",
      "@type": "QleverSparqlEngine",
      "rdfEngine": {
        "@id": "urn:undefineds:xpod:SolidRdfEngine"
      }
    },
    {
      "comment": "Use SolidRdfEngine for structured RDF data and local filesystem for other content.",
      "@id": "urn:undefineds:xpod:MixDataAccessor",
      "@type": "MixDataAccessor",
      "structuredDataAccessor": {
        "@id": "urn:undefineds:xpod:SolidRdfDataAccessor"
      },
      "unstructuredDataAccessor": {
        "@id": "urn:solid-server:default:FileDataAccessor"
      },
      "rdfFileDataAccessor": {
        "@id": "urn:solid-server:default:FileDataAccessor"
      },
      "rdfFileMapper": {
        "@id": "urn:solid-server:default:FileIdentifierMapper"
      },
      "textSearchIndexingEnabled": true,
      "localRdfAuthorityJournal": {
        "@id": "urn:undefineds:xpod:LocalRdfAuthorityJournal"
      },
      "rdfSearchIntentSink": {
        "@id": "urn:undefineds:xpod:RdfSearchIntentSink"
      }
    },
    {
      "comment": "Default structured RDF data accessor backed directly by SolidRdfEngine.",
      "@id": "urn:undefineds:xpod:SolidRdfDataAccessor",
      "@type": "SolidRdfDataAccessor",
      "rdfEngine": {
        "@id": "urn:undefineds:xpod:SolidRdfEngine"
      },
      "identifierStrategy": {
        "@id": "urn:solid-server:default:IdentifierStrategy"
      }
    },
    {
      "comment": "等位替换: 用 SparqlUpdateResourceStore 替换默认的 DataAccessorBasedStore",
      "@type": "Override",
      "overrideInstance": {
        "@id": "urn:solid-server:default:ResourceStore_Backend"
      },
      "overrideParameters": {
        "@type": "SparqlUpdateResourceStore",
        "identifierStrategy": {
          "@id": "urn:solid-server:default:IdentifierStrategy"
        },
        "auxiliaryStrategy": {
          "@id": "urn:solid-server:default:AuxiliaryStrategy"
        },
        "metadataStrategy": {
          "@id": "urn:solid-server:default:MetadataStrategy"
        },
        "accessor": {
          "@id": "urn:undefineds:xpod:MixDataAccessor"
        }
      }
    },
    {
      "comment": "等位替换: 用 RepresentationPartialConvertingStore 替换 Converting 层，只转换 RDF 类型",
      "@type": "Override",
      "overrideInstance": {
        "@id": "urn:solid-server:default:ResourceStore_Converting"
      },
      "overrideParameters": {
        "@type": "RepresentationPartialConvertingStore",
        "source": {
          "@id": "urn:solid-server:default:ResourceStore_Backend"
        },
        "metadataStrategy": {
          "@id": "urn:solid-server:default:MetadataStrategy"
        },
        "options_inConverter": {
          "@id": "urn:solid-server:default:RepresentationConverter"
        },
        "options_outConverter": {
          "@id": "urn:solid-server:default:RepresentationConverter"
        },
        "options_inPreferences_type": {
          "RepresentationPartialConvertingStore:_options_inPreferences_type_key": "internal/quads",
          "RepresentationPartialConvertingStore:_options_inPreferences_type_value": 1
        }
      }
    },
    {
      "comment": "等位替换: 用内存锁替换文件锁，避免高并发下的 ECOMPROMISED 错误",
      "@type": "Override",
      "overrideInstance": {
        "@id": "urn:solid-server:default:ResourceLocker"
      },
      "overrideParameters": {
        "@type": "WrappedExpiringReadWriteLocker",
        "locker": {
          "@type": "GreedyReadWriteLocker",
          "locker": {
            "@type": "MemoryResourceLocker"
          },
          "storage": {
            "@type": "MemoryMapStorage"
          }
        },
        "expiration": 6000
      }
    },
    {
      "comment": "Use SQLite-based KeyValueStorage for internal data (avoids .internal directory)",
      "@type": "Override",
      "overrideInstance": {
        "@id": "urn:solid-server:default:KeyValueStorage"
      },
      "overrideParameters": {
        "@type": "SqliteKeyValueStorage",
        "path": {
          "@id": "urn:solid-server:default:variable:identityDbUrl",
          "@type": "Variable"
        }
      }
    },
    {
      "@id": "urn:solid-server:default:variable:registration",
      "@value": true
    },
    {
      "comment": "Compose local HTTP pipeline without edge handlers",
      "@type": "Override",
      "overrideInstance": {
        "@id": "urn:solid-server:default:BaseHttpHandler"
      },
      "overrideParameters": {
        "@type": "StatusWaterfallHandler",
        "handlers": [
          {
            "@id": "urn:undefineds:xpod:InternalPodDataHttpHandler"
          },
          {
            "@id": "urn:undefineds:xpod:SubgraphSparqlHttpHandler"
          },
          {
            "@id": "urn:undefineds:xpod:VectorHttpHandler"
          },
          {
            "@id": "urn:undefineds:xpod:TerminalHttpHandler"
          },
          {
            "@id": "urn:undefineds:xpod:AppStaticAssetHandler"
          },
          {
            "@id": "urn:solid-server:default:StaticAssetHandler"
          },
          {
            "comment": "Local 模式下 OIDC discovery/token/JWKS 全部由 CSS 默认 OIDC handler 处理，避免本地 token 与外部 JWKS 错配",
            "@id": "urn:undefineds:xpod:AutoDetectOidcHandler"
          },
          {
            "@id": "urn:solid-server:default:OidcHandler"
          },
          {
            "@id": "urn:solid-server:default:NotificationHttpHandler"
          },
          {
            "@id": "urn:solid-server:default:StorageDescriptionHandler"
          },
          {
            "@id": "urn:solid-server:default:AuthResourceHttpHandler"
          },
          {
            "@id": "urn:solid-server:default:IdentityProviderHandler"
          },
          {
            "@id": "urn:solid-server:default:LdpHandler"
          }
        ]
      }
    }
  ]
}
