rust-kgdb 0.6.81 → 0.6.82
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +281 -0
- package/examples/rpc-catalog-dprod-demo.js +339 -0
- package/examples/rpc-federation-sql-demo.js +273 -0
- package/examples/rpc-virtual-tables-demo.js +268 -0
- package/hypermind-agent.js +626 -0
- package/index.d.ts +304 -0
- package/index.js +9 -0
- package/package.json +1 -1
package/hypermind-agent.js
CHANGED
|
@@ -1642,6 +1642,89 @@ class ProofDAG {
|
|
|
1642
1642
|
)
|
|
1643
1643
|
}
|
|
1644
1644
|
|
|
1645
|
+
/**
|
|
1646
|
+
* Add federation query as evidence (HyperFederate cross-database queries)
|
|
1647
|
+
*
|
|
1648
|
+
* Records federated SQL execution across KGDB + Snowflake + BigQuery as
|
|
1649
|
+
* provenance evidence in the proof DAG. Supports full lineage tracking
|
|
1650
|
+
* for cross-database queries with W3C PROV compatibility.
|
|
1651
|
+
*
|
|
1652
|
+
* @param {string} parentId - Parent node ID
|
|
1653
|
+
* @param {string} sql - Federated SQL query
|
|
1654
|
+
* @param {string[]} sources - Data sources involved (e.g., ['kgdb', 'snowflake', 'bigquery'])
|
|
1655
|
+
* @param {number} rowCount - Number of rows returned
|
|
1656
|
+
* @param {number} duration - Query duration in ms
|
|
1657
|
+
* @param {Object} metadata - Additional metadata (planHash, cached, etc.)
|
|
1658
|
+
* @returns {string} New node ID
|
|
1659
|
+
*/
|
|
1660
|
+
addFederationEvidence(parentId, sql, sources, rowCount, duration, metadata = {}) {
|
|
1661
|
+
return this.addEvidence(
|
|
1662
|
+
parentId,
|
|
1663
|
+
`Federated query across ${sources.join(', ')} returned ${rowCount} rows in ${duration}ms`,
|
|
1664
|
+
{
|
|
1665
|
+
type: 'federation',
|
|
1666
|
+
sql: sql.slice(0, 500), // Truncate long queries
|
|
1667
|
+
sources,
|
|
1668
|
+
rowCount,
|
|
1669
|
+
duration,
|
|
1670
|
+
planHash: metadata.planHash,
|
|
1671
|
+
cached: metadata.cached || false,
|
|
1672
|
+
// W3C PROV compatibility
|
|
1673
|
+
wasGeneratedBy: 'hyperfederate:QueryExecution',
|
|
1674
|
+
wasDerivedFrom: sources.map(s => `hyperfederate:DataSource/${s}`)
|
|
1675
|
+
},
|
|
1676
|
+
'FEDERATION_QUERY'
|
|
1677
|
+
)
|
|
1678
|
+
}
|
|
1679
|
+
|
|
1680
|
+
/**
|
|
1681
|
+
* Add virtual table creation as evidence
|
|
1682
|
+
*
|
|
1683
|
+
* @param {string} parentId - Parent node ID
|
|
1684
|
+
* @param {string} tableName - Virtual table name
|
|
1685
|
+
* @param {string} sql - SQL query that defines the virtual table
|
|
1686
|
+
* @param {number} rowCount - Number of rows materialized
|
|
1687
|
+
* @returns {string} New node ID
|
|
1688
|
+
*/
|
|
1689
|
+
addVirtualTableEvidence(parentId, tableName, sql, rowCount) {
|
|
1690
|
+
return this.addEvidence(
|
|
1691
|
+
parentId,
|
|
1692
|
+
`Created virtual table '${tableName}' with ${rowCount} rows`,
|
|
1693
|
+
{
|
|
1694
|
+
type: 'virtual_table',
|
|
1695
|
+
tableName,
|
|
1696
|
+
sql: sql.slice(0, 500),
|
|
1697
|
+
rowCount,
|
|
1698
|
+
wasGeneratedBy: 'hyperfederate:VirtualTableCreation'
|
|
1699
|
+
},
|
|
1700
|
+
'VIRTUAL_TABLE_CREATE'
|
|
1701
|
+
)
|
|
1702
|
+
}
|
|
1703
|
+
|
|
1704
|
+
/**
|
|
1705
|
+
* Add catalog registration as evidence
|
|
1706
|
+
*
|
|
1707
|
+
* @param {string} parentId - Parent node ID
|
|
1708
|
+
* @param {string} productName - Data product name
|
|
1709
|
+
* @param {string[]} sources - Data sources
|
|
1710
|
+
* @param {string} productId - Registered product ID
|
|
1711
|
+
* @returns {string} New node ID
|
|
1712
|
+
*/
|
|
1713
|
+
addCatalogEvidence(parentId, productName, sources, productId) {
|
|
1714
|
+
return this.addEvidence(
|
|
1715
|
+
parentId,
|
|
1716
|
+
`Registered data product '${productName}' from ${sources.length} sources`,
|
|
1717
|
+
{
|
|
1718
|
+
type: 'catalog',
|
|
1719
|
+
productName,
|
|
1720
|
+
productId,
|
|
1721
|
+
sources,
|
|
1722
|
+
wasGeneratedBy: 'hyperfederate:CatalogRegistration'
|
|
1723
|
+
},
|
|
1724
|
+
'CATALOG_REGISTER'
|
|
1725
|
+
)
|
|
1726
|
+
}
|
|
1727
|
+
|
|
1645
1728
|
/**
|
|
1646
1729
|
* Compute deterministic hash of entire proof
|
|
1647
1730
|
*/
|
|
@@ -1819,6 +1902,542 @@ const TOOL_REGISTRY = {
|
|
|
1819
1902
|
output: 'Distances',
|
|
1820
1903
|
description: 'Compute shortest paths from landmarks',
|
|
1821
1904
|
domain: 'kg'
|
|
1905
|
+
},
|
|
1906
|
+
|
|
1907
|
+
// ============================================================================
|
|
1908
|
+
// HyperFederate Federation Tools (Category Theory: Typed Morphisms)
|
|
1909
|
+
// Cross-database federation: KGDB + Snowflake + BigQuery + PostgreSQL + MySQL
|
|
1910
|
+
// ============================================================================
|
|
1911
|
+
|
|
1912
|
+
'federation.sql.query': {
|
|
1913
|
+
name: 'federation.sql.query',
|
|
1914
|
+
input: 'FederatedQuery',
|
|
1915
|
+
output: 'RecordBatch',
|
|
1916
|
+
description: 'Execute federated SQL across KGDB + Snowflake + BigQuery',
|
|
1917
|
+
domain: 'federation',
|
|
1918
|
+
patterns: {
|
|
1919
|
+
cross_join: 'SELECT kg.*, sf.* FROM graph_search(...) kg JOIN snowflake.table sf ON ...',
|
|
1920
|
+
three_way: 'SELECT kg.*, sf.*, bq.* FROM graph_search(...) kg JOIN ... JOIN ...'
|
|
1921
|
+
},
|
|
1922
|
+
connectors: ['kgdb', 'snowflake', 'bigquery', 'postgres', 'mysql']
|
|
1923
|
+
},
|
|
1924
|
+
'federation.virtual.create': {
|
|
1925
|
+
name: 'federation.virtual.create',
|
|
1926
|
+
input: 'VirtualTableSpec',
|
|
1927
|
+
output: 'VirtualTableId',
|
|
1928
|
+
description: 'Create session-bound virtual table from federation query',
|
|
1929
|
+
domain: 'federation'
|
|
1930
|
+
},
|
|
1931
|
+
'federation.virtual.query': {
|
|
1932
|
+
name: 'federation.virtual.query',
|
|
1933
|
+
input: 'VirtualTableQuery',
|
|
1934
|
+
output: 'RecordBatch',
|
|
1935
|
+
description: 'Query existing virtual table',
|
|
1936
|
+
domain: 'federation'
|
|
1937
|
+
},
|
|
1938
|
+
'federation.catalog.list': {
|
|
1939
|
+
name: 'federation.catalog.list',
|
|
1940
|
+
input: 'CatalogFilter',
|
|
1941
|
+
output: 'DataProductList',
|
|
1942
|
+
description: 'List data products in DCAT DPROD catalog',
|
|
1943
|
+
domain: 'federation'
|
|
1944
|
+
},
|
|
1945
|
+
'federation.catalog.register': {
|
|
1946
|
+
name: 'federation.catalog.register',
|
|
1947
|
+
input: 'DataProductSpec',
|
|
1948
|
+
output: 'DataProductId',
|
|
1949
|
+
description: 'Register data product in catalog',
|
|
1950
|
+
domain: 'federation'
|
|
1951
|
+
},
|
|
1952
|
+
'federation.udf.call': {
|
|
1953
|
+
name: 'federation.udf.call',
|
|
1954
|
+
input: 'UdfCall',
|
|
1955
|
+
output: 'UdfResult',
|
|
1956
|
+
description: 'Call semantic UDF (similar_to, neighbors, entity_type, etc.)',
|
|
1957
|
+
domain: 'federation',
|
|
1958
|
+
udfs: ['similar_to', 'text_search', 'neighbors', 'graph_pattern', 'sparql_query', 'entity_type', 'entity_properties']
|
|
1959
|
+
},
|
|
1960
|
+
'federation.table_function.call': {
|
|
1961
|
+
name: 'federation.table_function.call',
|
|
1962
|
+
input: 'TableFunctionCall',
|
|
1963
|
+
output: 'RecordBatch',
|
|
1964
|
+
description: 'Call table function (graph_search, vector_search, pagerank, etc.)',
|
|
1965
|
+
domain: 'federation',
|
|
1966
|
+
functions: ['graph_search', 'vector_search', 'pagerank', 'connected_components', 'shortest_paths', 'triangle_count', 'label_propagation', 'datalog_reason', 'motif_search']
|
|
1967
|
+
}
|
|
1968
|
+
}
|
|
1969
|
+
|
|
1970
|
+
// Federation tools as separate constant for easy access
|
|
1971
|
+
const FEDERATION_TOOLS = {
|
|
1972
|
+
'federation.sql.query': TOOL_REGISTRY['federation.sql.query'],
|
|
1973
|
+
'federation.virtual.create': TOOL_REGISTRY['federation.virtual.create'],
|
|
1974
|
+
'federation.virtual.query': TOOL_REGISTRY['federation.virtual.query'],
|
|
1975
|
+
'federation.catalog.list': TOOL_REGISTRY['federation.catalog.list'],
|
|
1976
|
+
'federation.catalog.register': TOOL_REGISTRY['federation.catalog.register'],
|
|
1977
|
+
'federation.udf.call': TOOL_REGISTRY['federation.udf.call'],
|
|
1978
|
+
'federation.table_function.call': TOOL_REGISTRY['federation.table_function.call']
|
|
1979
|
+
}
|
|
1980
|
+
|
|
1981
|
+
// ============================================================================
|
|
1982
|
+
// RPC FEDERATION PROXY - WASM RPC proxy for HyperFederate
|
|
1983
|
+
// ============================================================================
|
|
1984
|
+
|
|
1985
|
+
/**
|
|
1986
|
+
* RpcFederationProxy - WASM RPC proxy for HyperFederate cross-database federation
|
|
1987
|
+
*
|
|
1988
|
+
* This follows the same pattern as RpcKgdbStore mentioned in index.js:
|
|
1989
|
+
* "NOTE: QueryMemoryStore, HybridReranker, TriggerManager moved to Rust core
|
|
1990
|
+
* Access via HyperAgentProxy/WASM runtime (SDK remains thin)"
|
|
1991
|
+
*
|
|
1992
|
+
* Category Theory: Proxy is a natural transformation between local and remote execution
|
|
1993
|
+
* Type Theory: All operations are typed morphisms (Input → Output)
|
|
1994
|
+
* Proof Theory: Full audit log with provenance tracking
|
|
1995
|
+
*
|
|
1996
|
+
* Supports:
|
|
1997
|
+
* - Cross-database SQL: KGDB + Snowflake + BigQuery + PostgreSQL + MySQL
|
|
1998
|
+
* - Virtual Tables: Session-bound query result materialization
|
|
1999
|
+
* - Data Catalog: DCAT DPROD ontology for data product registration
|
|
2000
|
+
* - Semantic UDFs: 7 AI-powered functions (similar_to, neighbors, etc.)
|
|
2001
|
+
* - Table Functions: 9 graph analytics (graph_search, pagerank, etc.)
|
|
2002
|
+
*/
|
|
2003
|
+
class RpcFederationProxy {
|
|
2004
|
+
/**
|
|
2005
|
+
* Create a new RpcFederationProxy
|
|
2006
|
+
* @param {Object} config - Configuration options
|
|
2007
|
+
* @param {string} config.endpoint - HyperFederate server endpoint (default: http://localhost:30180)
|
|
2008
|
+
* @param {number} config.timeout - Request timeout in ms (default: 30000)
|
|
2009
|
+
* @param {WasmSandbox} config.sandbox - WasmSandbox for capability-based security
|
|
2010
|
+
* @param {Object} config.headers - Additional HTTP headers
|
|
2011
|
+
*/
|
|
2012
|
+
constructor(config = {}) {
|
|
2013
|
+
this.endpoint = config.endpoint || 'http://localhost:30180'
|
|
2014
|
+
this.timeout = config.timeout || 30000
|
|
2015
|
+
this.headers = config.headers || {}
|
|
2016
|
+
|
|
2017
|
+
// WasmSandbox for capability-based security with fuel metering
|
|
2018
|
+
// Includes 'Federation' capability for cross-database operations
|
|
2019
|
+
this.sandbox = config.sandbox || new WasmSandbox({
|
|
2020
|
+
capabilities: ['ReadKG', 'ExecuteTool', 'Federation'],
|
|
2021
|
+
fuelLimit: 100000
|
|
2022
|
+
})
|
|
2023
|
+
|
|
2024
|
+
// Audit log for provenance tracking (Proof Theory)
|
|
2025
|
+
this.auditLog = []
|
|
2026
|
+
|
|
2027
|
+
// Session ID for virtual table isolation
|
|
2028
|
+
this.sessionId = config.sessionId || `session-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`
|
|
2029
|
+
|
|
2030
|
+
// Identity for access control
|
|
2031
|
+
this.identityId = config.identityId || 'anonymous'
|
|
2032
|
+
}
|
|
2033
|
+
|
|
2034
|
+
/**
|
|
2035
|
+
* Execute federated SQL query across multiple data sources
|
|
2036
|
+
*
|
|
2037
|
+
* Category Theory: FederatedQuery → RecordBatch morphism
|
|
2038
|
+
*
|
|
2039
|
+
* @param {string} sql - Federated SQL query (supports graph_search, snowflake.*, bigquery.*, etc.)
|
|
2040
|
+
* @param {Object} options - Query options
|
|
2041
|
+
* @param {number} options.limit - Result limit
|
|
2042
|
+
* @param {number} options.timeout - Query timeout in ms
|
|
2043
|
+
* @returns {Promise<Object>} RecordBatch result with columns, rows, metadata
|
|
2044
|
+
*
|
|
2045
|
+
* @example
|
|
2046
|
+
* const result = await proxy.query(`
|
|
2047
|
+
* SELECT kg.person, kg.riskScore, sf.C_NAME, sf.C_ACCTBAL
|
|
2048
|
+
* FROM graph_search('PREFIX finance: ... SELECT ?person ?riskScore WHERE {...}') kg
|
|
2049
|
+
* JOIN snowflake_tpch.CUSTOMER sf ON CAST(kg.custKey AS INT) = sf.C_CUSTKEY
|
|
2050
|
+
* LIMIT 10
|
|
2051
|
+
* `)
|
|
2052
|
+
*/
|
|
2053
|
+
async query(sql, options = {}) {
|
|
2054
|
+
// Check capability
|
|
2055
|
+
if (!this.sandbox.hasCapability('Federation')) {
|
|
2056
|
+
throw new Error('Federation capability not granted')
|
|
2057
|
+
}
|
|
2058
|
+
|
|
2059
|
+
// Consume fuel for operation
|
|
2060
|
+
this.sandbox.consumeFuel(1000)
|
|
2061
|
+
|
|
2062
|
+
const start = Date.now()
|
|
2063
|
+
|
|
2064
|
+
try {
|
|
2065
|
+
// RPC call to HyperFederate server
|
|
2066
|
+
const response = await fetch(`${this.endpoint}/api/v1/query`, {
|
|
2067
|
+
method: 'POST',
|
|
2068
|
+
headers: {
|
|
2069
|
+
'Content-Type': 'application/json',
|
|
2070
|
+
'X-Session-Id': this.sessionId,
|
|
2071
|
+
'X-Identity-Id': this.identityId,
|
|
2072
|
+
...this.headers
|
|
2073
|
+
},
|
|
2074
|
+
body: JSON.stringify({
|
|
2075
|
+
sql,
|
|
2076
|
+
limit: options.limit,
|
|
2077
|
+
timeout: options.timeout || this.timeout
|
|
2078
|
+
}),
|
|
2079
|
+
signal: AbortSignal.timeout(options.timeout || this.timeout)
|
|
2080
|
+
})
|
|
2081
|
+
|
|
2082
|
+
if (!response.ok) {
|
|
2083
|
+
const error = await response.text()
|
|
2084
|
+
throw new Error(`Federation query failed: ${error}`)
|
|
2085
|
+
}
|
|
2086
|
+
|
|
2087
|
+
const result = await response.json()
|
|
2088
|
+
const duration = Date.now() - start
|
|
2089
|
+
|
|
2090
|
+
// Log to sandbox audit trail
|
|
2091
|
+
this.sandbox.log('federation.sql.query', { sql: sql.slice(0, 200) }, result, 'success')
|
|
2092
|
+
|
|
2093
|
+
// Add to audit log for provenance
|
|
2094
|
+
this.auditLog.push({
|
|
2095
|
+
action: 'query',
|
|
2096
|
+
sql,
|
|
2097
|
+
duration,
|
|
2098
|
+
rows: result.rows?.length || 0,
|
|
2099
|
+
timestamp: new Date().toISOString(),
|
|
2100
|
+
sessionId: this.sessionId
|
|
2101
|
+
})
|
|
2102
|
+
|
|
2103
|
+
return {
|
|
2104
|
+
columns: result.columns || [],
|
|
2105
|
+
rows: result.rows || [],
|
|
2106
|
+
rowCount: result.rows?.length || 0,
|
|
2107
|
+
duration,
|
|
2108
|
+
metadata: {
|
|
2109
|
+
sources: result.sources || [],
|
|
2110
|
+
planHash: result.planHash,
|
|
2111
|
+
cached: result.cached || false
|
|
2112
|
+
}
|
|
2113
|
+
}
|
|
2114
|
+
} catch (error) {
|
|
2115
|
+
this.sandbox.log('federation.sql.query', { sql: sql.slice(0, 200) }, null, 'error')
|
|
2116
|
+
this.auditLog.push({
|
|
2117
|
+
action: 'query',
|
|
2118
|
+
sql,
|
|
2119
|
+
error: error.message,
|
|
2120
|
+
timestamp: new Date().toISOString(),
|
|
2121
|
+
sessionId: this.sessionId
|
|
2122
|
+
})
|
|
2123
|
+
throw error
|
|
2124
|
+
}
|
|
2125
|
+
}
|
|
2126
|
+
|
|
2127
|
+
/**
|
|
2128
|
+
* Create a virtual table from a federation query result
|
|
2129
|
+
*
|
|
2130
|
+
* Category Theory: VirtualTableSpec → VirtualTableId morphism
|
|
2131
|
+
*
|
|
2132
|
+
* Virtual tables are session-bound, stored as RDF triples in KGDB,
|
|
2133
|
+
* and support access control via shared_with and shared_with_groups.
|
|
2134
|
+
*
|
|
2135
|
+
* @param {string} name - Virtual table name
|
|
2136
|
+
* @param {string} sql - SQL query that defines the virtual table
|
|
2137
|
+
* @param {Object} options - Virtual table options
|
|
2138
|
+
* @param {string} options.refreshPolicy - 'on_demand' | 'ttl' | 'on_source_change'
|
|
2139
|
+
* @param {number} options.ttlSeconds - TTL in seconds (for 'ttl' policy)
|
|
2140
|
+
* @param {string[]} options.sharedWith - Identity IDs to share with
|
|
2141
|
+
* @param {string[]} options.sharedWithGroups - Group IDs to share with
|
|
2142
|
+
* @returns {Promise<Object>} Virtual table metadata
|
|
2143
|
+
*
|
|
2144
|
+
* @example
|
|
2145
|
+
* const vt = await proxy.createVirtualTable('high_risk_customers', `
|
|
2146
|
+
* SELECT kg.*, sf.C_ACCTBAL
|
|
2147
|
+
* FROM graph_search('...') kg
|
|
2148
|
+
* JOIN snowflake.CUSTOMER sf ON ...
|
|
2149
|
+
* WHERE kg.riskScore > 0.8
|
|
2150
|
+
* `, { refreshPolicy: 'on_demand', ttlSeconds: 3600 })
|
|
2151
|
+
*/
|
|
2152
|
+
async createVirtualTable(name, sql, options = {}) {
|
|
2153
|
+
if (!this.sandbox.hasCapability('Federation')) {
|
|
2154
|
+
throw new Error('Federation capability not granted')
|
|
2155
|
+
}
|
|
2156
|
+
|
|
2157
|
+
this.sandbox.consumeFuel(500)
|
|
2158
|
+
const start = Date.now()
|
|
2159
|
+
|
|
2160
|
+
try {
|
|
2161
|
+
const response = await fetch(`${this.endpoint}/api/v1/tables`, {
|
|
2162
|
+
method: 'POST',
|
|
2163
|
+
headers: {
|
|
2164
|
+
'Content-Type': 'application/json',
|
|
2165
|
+
'X-Session-Id': this.sessionId,
|
|
2166
|
+
'X-Identity-Id': this.identityId,
|
|
2167
|
+
...this.headers
|
|
2168
|
+
},
|
|
2169
|
+
body: JSON.stringify({
|
|
2170
|
+
name,
|
|
2171
|
+
sql,
|
|
2172
|
+
refreshPolicy: options.refreshPolicy || 'on_demand',
|
|
2173
|
+
ttlSeconds: options.ttlSeconds || 3600,
|
|
2174
|
+
sharedWith: options.sharedWith || [],
|
|
2175
|
+
sharedWithGroups: options.sharedWithGroups || []
|
|
2176
|
+
}),
|
|
2177
|
+
signal: AbortSignal.timeout(this.timeout)
|
|
2178
|
+
})
|
|
2179
|
+
|
|
2180
|
+
if (!response.ok) {
|
|
2181
|
+
const error = await response.text()
|
|
2182
|
+
throw new Error(`Create virtual table failed: ${error}`)
|
|
2183
|
+
}
|
|
2184
|
+
|
|
2185
|
+
const result = await response.json()
|
|
2186
|
+
const duration = Date.now() - start
|
|
2187
|
+
|
|
2188
|
+
this.sandbox.log('federation.virtual.create', { name, sql: sql.slice(0, 100) }, result, 'success')
|
|
2189
|
+
this.auditLog.push({
|
|
2190
|
+
action: 'createVirtualTable',
|
|
2191
|
+
name,
|
|
2192
|
+
sql,
|
|
2193
|
+
duration,
|
|
2194
|
+
timestamp: new Date().toISOString(),
|
|
2195
|
+
sessionId: this.sessionId
|
|
2196
|
+
})
|
|
2197
|
+
|
|
2198
|
+
return {
|
|
2199
|
+
id: result.id,
|
|
2200
|
+
name: result.name || name,
|
|
2201
|
+
uri: result.uri,
|
|
2202
|
+
columns: result.columns || [],
|
|
2203
|
+
rowCount: result.rowCount,
|
|
2204
|
+
refreshPolicy: options.refreshPolicy || 'on_demand',
|
|
2205
|
+
createdAt: new Date().toISOString()
|
|
2206
|
+
}
|
|
2207
|
+
} catch (error) {
|
|
2208
|
+
this.sandbox.log('federation.virtual.create', { name }, null, 'error')
|
|
2209
|
+
throw error
|
|
2210
|
+
}
|
|
2211
|
+
}
|
|
2212
|
+
|
|
2213
|
+
/**
|
|
2214
|
+
* Query a virtual table
|
|
2215
|
+
*
|
|
2216
|
+
* @param {string} name - Virtual table name
|
|
2217
|
+
* @param {string} whereClauses - Optional WHERE clause conditions
|
|
2218
|
+
* @returns {Promise<Object>} Query result
|
|
2219
|
+
*/
|
|
2220
|
+
async queryVirtualTable(name, whereClauses = '') {
|
|
2221
|
+
const sql = `SELECT * FROM virtual.${name}${whereClauses ? ` WHERE ${whereClauses}` : ''}`
|
|
2222
|
+
return this.query(sql)
|
|
2223
|
+
}
|
|
2224
|
+
|
|
2225
|
+
/**
|
|
2226
|
+
* List data products in the DCAT DPROD catalog
|
|
2227
|
+
*
|
|
2228
|
+
* Category Theory: CatalogFilter → DataProductList morphism
|
|
2229
|
+
*
|
|
2230
|
+
* @param {Object} filter - Filter options
|
|
2231
|
+
* @param {string} filter.owner - Filter by owner
|
|
2232
|
+
* @param {string[]} filter.sources - Filter by data sources
|
|
2233
|
+
* @param {string} filter.search - Search in name/description
|
|
2234
|
+
* @returns {Promise<Object[]>} List of data products
|
|
2235
|
+
*/
|
|
2236
|
+
async listCatalog(filter = {}) {
|
|
2237
|
+
if (!this.sandbox.hasCapability('ReadKG')) {
|
|
2238
|
+
throw new Error('ReadKG capability not granted')
|
|
2239
|
+
}
|
|
2240
|
+
|
|
2241
|
+
this.sandbox.consumeFuel(100)
|
|
2242
|
+
|
|
2243
|
+
try {
|
|
2244
|
+
const params = new URLSearchParams()
|
|
2245
|
+
if (filter.owner) params.set('owner', filter.owner)
|
|
2246
|
+
if (filter.sources) params.set('sources', filter.sources.join(','))
|
|
2247
|
+
if (filter.search) params.set('search', filter.search)
|
|
2248
|
+
|
|
2249
|
+
const url = `${this.endpoint}/api/v1/catalog${params.toString() ? '?' + params.toString() : ''}`
|
|
2250
|
+
|
|
2251
|
+
const response = await fetch(url, {
|
|
2252
|
+
method: 'GET',
|
|
2253
|
+
headers: {
|
|
2254
|
+
'Content-Type': 'application/json',
|
|
2255
|
+
'X-Session-Id': this.sessionId,
|
|
2256
|
+
'X-Identity-Id': this.identityId,
|
|
2257
|
+
...this.headers
|
|
2258
|
+
},
|
|
2259
|
+
signal: AbortSignal.timeout(this.timeout)
|
|
2260
|
+
})
|
|
2261
|
+
|
|
2262
|
+
if (!response.ok) {
|
|
2263
|
+
const error = await response.text()
|
|
2264
|
+
throw new Error(`List catalog failed: ${error}`)
|
|
2265
|
+
}
|
|
2266
|
+
|
|
2267
|
+
const result = await response.json()
|
|
2268
|
+
this.sandbox.log('federation.catalog.list', filter, result, 'success')
|
|
2269
|
+
|
|
2270
|
+
return result.products || result
|
|
2271
|
+
} catch (error) {
|
|
2272
|
+
this.sandbox.log('federation.catalog.list', filter, null, 'error')
|
|
2273
|
+
throw error
|
|
2274
|
+
}
|
|
2275
|
+
}
|
|
2276
|
+
|
|
2277
|
+
/**
|
|
2278
|
+
* Register a data product in the DCAT DPROD catalog
|
|
2279
|
+
*
|
|
2280
|
+
* Category Theory: DataProductSpec → DataProductId morphism
|
|
2281
|
+
*
|
|
2282
|
+
* @param {Object} spec - Data product specification
|
|
2283
|
+
* @param {string} spec.name - Product name
|
|
2284
|
+
* @param {string} spec.description - Product description
|
|
2285
|
+
* @param {string[]} spec.sources - Data source identifiers
|
|
2286
|
+
* @param {string} spec.outputPort - API endpoint for querying
|
|
2287
|
+
* @param {Object} spec.schema - Column schema definition
|
|
2288
|
+
* @param {Object} spec.quality - Quality metrics (completeness, accuracy)
|
|
2289
|
+
* @param {string} spec.owner - Owner identity
|
|
2290
|
+
* @returns {Promise<Object>} Registered data product with ID
|
|
2291
|
+
*
|
|
2292
|
+
* @example
|
|
2293
|
+
* const product = await proxy.registerDataProduct({
|
|
2294
|
+
* name: 'High Risk Customer Analysis',
|
|
2295
|
+
* description: 'Cross-domain risk scoring combining KG + transactional data',
|
|
2296
|
+
* sources: ['kgdb', 'snowflake', 'bigquery'],
|
|
2297
|
+
* outputPort: '/api/v1/products/high-risk/query',
|
|
2298
|
+
* schema: { columns: [{ name: 'entity', type: 'STRING' }, ...] },
|
|
2299
|
+
* quality: { completeness: 0.98, accuracy: 0.95 },
|
|
2300
|
+
* owner: 'risk-analytics-team'
|
|
2301
|
+
* })
|
|
2302
|
+
*/
|
|
2303
|
+
async registerDataProduct(spec) {
|
|
2304
|
+
if (!this.sandbox.hasCapability('Federation')) {
|
|
2305
|
+
throw new Error('Federation capability not granted')
|
|
2306
|
+
}
|
|
2307
|
+
|
|
2308
|
+
this.sandbox.consumeFuel(500)
|
|
2309
|
+
|
|
2310
|
+
try {
|
|
2311
|
+
const response = await fetch(`${this.endpoint}/api/v1/catalog`, {
|
|
2312
|
+
method: 'POST',
|
|
2313
|
+
headers: {
|
|
2314
|
+
'Content-Type': 'application/json',
|
|
2315
|
+
'X-Session-Id': this.sessionId,
|
|
2316
|
+
'X-Identity-Id': this.identityId,
|
|
2317
|
+
...this.headers
|
|
2318
|
+
},
|
|
2319
|
+
body: JSON.stringify(spec),
|
|
2320
|
+
signal: AbortSignal.timeout(this.timeout)
|
|
2321
|
+
})
|
|
2322
|
+
|
|
2323
|
+
if (!response.ok) {
|
|
2324
|
+
const error = await response.text()
|
|
2325
|
+
throw new Error(`Register data product failed: ${error}`)
|
|
2326
|
+
}
|
|
2327
|
+
|
|
2328
|
+
const result = await response.json()
|
|
2329
|
+
this.sandbox.log('federation.catalog.register', { name: spec.name }, result, 'success')
|
|
2330
|
+
|
|
2331
|
+
this.auditLog.push({
|
|
2332
|
+
action: 'registerDataProduct',
|
|
2333
|
+
name: spec.name,
|
|
2334
|
+
sources: spec.sources,
|
|
2335
|
+
timestamp: new Date().toISOString(),
|
|
2336
|
+
sessionId: this.sessionId
|
|
2337
|
+
})
|
|
2338
|
+
|
|
2339
|
+
return {
|
|
2340
|
+
id: result.id,
|
|
2341
|
+
uri: result.uri,
|
|
2342
|
+
name: spec.name,
|
|
2343
|
+
createdAt: new Date().toISOString()
|
|
2344
|
+
}
|
|
2345
|
+
} catch (error) {
|
|
2346
|
+
this.sandbox.log('federation.catalog.register', { name: spec.name }, null, 'error')
|
|
2347
|
+
throw error
|
|
2348
|
+
}
|
|
2349
|
+
}
|
|
2350
|
+
|
|
2351
|
+
/**
|
|
2352
|
+
* Call a semantic UDF (one of 7 AI-powered functions)
|
|
2353
|
+
*
|
|
2354
|
+
* Available UDFs:
|
|
2355
|
+
* - similar_to(entity, threshold) - Find semantically similar entities via RDF2Vec
|
|
2356
|
+
* - text_search(query, limit) - Semantic text search
|
|
2357
|
+
* - neighbors(entity, hops) - N-hop graph traversal
|
|
2358
|
+
* - graph_pattern(s, p, o) - Triple pattern matching
|
|
2359
|
+
* - sparql_query(sparql) - Inline SPARQL execution
|
|
2360
|
+
* - entity_type(entity) - Get RDF types
|
|
2361
|
+
* - entity_properties(entity) - Get all properties
|
|
2362
|
+
*
|
|
2363
|
+
* @param {string} udfName - UDF function name
|
|
2364
|
+
* @param {Array} args - UDF arguments
|
|
2365
|
+
* @returns {Promise<Object>} UDF result
|
|
2366
|
+
*/
|
|
2367
|
+
async callUdf(udfName, ...args) {
|
|
2368
|
+
const validUdfs = ['similar_to', 'text_search', 'neighbors', 'graph_pattern', 'sparql_query', 'entity_type', 'entity_properties']
|
|
2369
|
+
if (!validUdfs.includes(udfName)) {
|
|
2370
|
+
throw new Error(`Unknown UDF: ${udfName}. Valid UDFs: ${validUdfs.join(', ')}`)
|
|
2371
|
+
}
|
|
2372
|
+
|
|
2373
|
+
// Build SQL with UDF call
|
|
2374
|
+
const argsStr = args.map(a => typeof a === 'string' ? `'${a}'` : a).join(', ')
|
|
2375
|
+
const sql = `SELECT ${udfName}(${argsStr}) AS result`
|
|
2376
|
+
|
|
2377
|
+
return this.query(sql)
|
|
2378
|
+
}
|
|
2379
|
+
|
|
2380
|
+
/**
|
|
2381
|
+
* Call a table function (one of 9 graph analytics functions)
|
|
2382
|
+
*
|
|
2383
|
+
* Available table functions:
|
|
2384
|
+
* - graph_search(sparql) - SPARQL → SQL bridge
|
|
2385
|
+
* - vector_search(text, k, threshold) - Semantic similarity search
|
|
2386
|
+
* - pagerank(sparql, damping, iterations) - PageRank centrality
|
|
2387
|
+
* - connected_components(sparql) - Community detection
|
|
2388
|
+
* - shortest_paths(src, dst, max_hops) - Path finding
|
|
2389
|
+
* - triangle_count(sparql) - Graph density measure
|
|
2390
|
+
* - label_propagation(sparql, iterations) - Community detection
|
|
2391
|
+
* - datalog_reason(rules) - Datalog inference
|
|
2392
|
+
* - motif_search(pattern) - Graph pattern matching
|
|
2393
|
+
*
|
|
2394
|
+
* @param {string} functionName - Table function name
|
|
2395
|
+
* @param {Array} args - Function arguments
|
|
2396
|
+
* @returns {Promise<Object>} RecordBatch result
|
|
2397
|
+
*/
|
|
2398
|
+
async callTableFunction(functionName, ...args) {
|
|
2399
|
+
const validFunctions = ['graph_search', 'vector_search', 'pagerank', 'connected_components', 'shortest_paths', 'triangle_count', 'label_propagation', 'datalog_reason', 'motif_search']
|
|
2400
|
+
if (!validFunctions.includes(functionName)) {
|
|
2401
|
+
throw new Error(`Unknown table function: ${functionName}. Valid functions: ${validFunctions.join(', ')}`)
|
|
2402
|
+
}
|
|
2403
|
+
|
|
2404
|
+
const argsStr = args.map(a => typeof a === 'string' ? `'${a}'` : a).join(', ')
|
|
2405
|
+
const sql = `SELECT * FROM ${functionName}(${argsStr})`
|
|
2406
|
+
|
|
2407
|
+
return this.query(sql)
|
|
2408
|
+
}
|
|
2409
|
+
|
|
2410
|
+
/**
|
|
2411
|
+
* Get the audit log for provenance tracking
|
|
2412
|
+
*
|
|
2413
|
+
* @returns {Array<Object>} Audit log entries
|
|
2414
|
+
*/
|
|
2415
|
+
getAuditLog() {
|
|
2416
|
+
return [...this.auditLog]
|
|
2417
|
+
}
|
|
2418
|
+
|
|
2419
|
+
/**
|
|
2420
|
+
* Clear the audit log
|
|
2421
|
+
*/
|
|
2422
|
+
clearAuditLog() {
|
|
2423
|
+
this.auditLog = []
|
|
2424
|
+
}
|
|
2425
|
+
|
|
2426
|
+
/**
|
|
2427
|
+
* Get sandbox fuel remaining
|
|
2428
|
+
* @returns {number} Fuel remaining
|
|
2429
|
+
*/
|
|
2430
|
+
getFuelRemaining() {
|
|
2431
|
+
return this.sandbox.fuel
|
|
2432
|
+
}
|
|
2433
|
+
|
|
2434
|
+
/**
|
|
2435
|
+
* Check if a capability is granted
|
|
2436
|
+
* @param {string} capability - Capability name
|
|
2437
|
+
* @returns {boolean} True if capability is granted
|
|
2438
|
+
*/
|
|
2439
|
+
hasCapability(capability) {
|
|
2440
|
+
return this.sandbox.hasCapability(capability)
|
|
1822
2441
|
}
|
|
1823
2442
|
}
|
|
1824
2443
|
|
|
@@ -4845,6 +5464,13 @@ module.exports = {
|
|
|
4845
5464
|
LLMPlanner,
|
|
4846
5465
|
TOOL_REGISTRY,
|
|
4847
5466
|
|
|
5467
|
+
// HyperFederate (v0.7.0+) - Cross-Database Federation
|
|
5468
|
+
// Query across KGDB + Snowflake + BigQuery in single SQL
|
|
5469
|
+
// Category Theory: Tools as typed morphisms (Input → Output)
|
|
5470
|
+
// Proof Theory: Full lineage tracking with W3C PROV
|
|
5471
|
+
RpcFederationProxy, // WASM RPC proxy for federated queries
|
|
5472
|
+
FEDERATION_TOOLS, // 7 federation tools as typed morphisms
|
|
5473
|
+
|
|
4848
5474
|
// Context Theory (v0.6.11+) - Type-theoretic foundations for SPARQL validation
|
|
4849
5475
|
// Based on: Spivak's Ologs, Functorial Data Migration, TypeQL
|
|
4850
5476
|
SchemaContext, // Γ context with classes, properties, bindings
|