Skip to content
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
985cfb8
Capture all outstanding changes
martindale Apr 24, 2026
8589f59
Snapshot latest changes
martindale Apr 25, 2026
2ce84a4
Update setup flow
martindale Apr 25, 2026
2faf758
General update to fix tests
martindale Apr 28, 2026
9f26023
Update flags
martindale Apr 28, 2026
4023902
Fix a variety of API-related issues
martindale Apr 28, 2026
037114a
General improvement to 402 flow
martindale Apr 28, 2026
6176fb4
Add missing function
martindale Apr 28, 2026
f6c850e
Use latest Fabric
martindale Apr 28, 2026
3b6e2ab
Add fabricDocumentOfferEnvelope
martindale Apr 28, 2026
41a7d72
Use latest Fabric
martindale Apr 30, 2026
fe21f7f
Add self-destruct
martindale May 4, 2026
e919031
Refactor out custom routes, defer to @fabric/http
martindale May 5, 2026
32811f7
Expand tests, remedy identity locking / login
martindale May 7, 2026
855a1af
Use latest Fabric
martindale May 9, 2026
0afeb47
Use latest Fabric, fix tests
martindale May 10, 2026
2e5ea9b
Snapshot of outstanding work for RSI
martindale Jun 25, 2026
2258076
Update package-lock.json, install report
martindale Jul 19, 2026
c7822bd
Update registry, use latest Fabric
martindale Jul 20, 2026
ad744ec
Use latest Fabric
martindale Jul 20, 2026
73d19fa
General sweep of RSI updates
martindale Jul 25, 2026
7411a33
Add all functions
martindale Jul 28, 2026
745b951
Major sweep of updates from Fabric
martindale Aug 6, 2026
f088ec8
Update npm requirements, remove dependency-tree
martindale Aug 6, 2026
6804251
Use latest Fabric
martindale Aug 6, 2026
fd03f72
Provide better API surface for peering
martindale Aug 7, 2026
bda2613
Use latest Fabric
martindale Aug 7, 2026
6f05f0b
Use latest Fabric
martindale Aug 11, 2026
279356f
Add various downstream APIs
martindale Aug 11, 2026
3d23d1d
Utilize new Fabric features, update various packages
martindale Aug 12, 2026
a755745
Use latest Fabric
martindale Aug 12, 2026
5657de2
Use latest Fabric
martindale Aug 12, 2026
c509f09
Use latest Fabric
martindale Aug 12, 2026
e9e8630
Use latest Fabric
martindale Aug 12, 2026
d6d7c34
Update AUDIT, SECURITY, use latest Fabric
martindale Aug 12, 2026
65b220a
Use latest Fabric
martindale Aug 12, 2026
ad04f60
Add hallmarks
martindale Aug 12, 2026
906acf6
Restore upper Beacon
martindale Aug 13, 2026
a771b20
Use latest Fabric
martindale Aug 13, 2026
5441f83
Use latest Fabric, update Document Market
martindale Aug 14, 2026
c4efe57
Add Codacy filter, use latest Fabric
martindale Aug 14, 2026
3cc43d1
Use latest Fabric, address some security issues
martindale Aug 14, 2026
da0d16f
General sweep of upstream Fabric and downstream consumer changes
martindale Aug 14, 2026
4c1cd14
Use latest Fabric, prepare for various downstream applications
martindale Aug 14, 2026
b6d8010
Use latest Fabric
martindale Aug 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .codacy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ engines:
# Semgrep browser/localStorage/HTTP FPs: storage keys, hub RPC, validated probes, server paths.
- "constants.js"
- "services/hub.js"
- "electron/desktopHubProbe.js"
- "scripts/desktopHubProbe.js"
- "functions/bitcoinClient.js"
- "functions/fabricMessageEnvelope.js"
- "functions/hubUiAlerts.js"
Expand Down
335 changes: 335 additions & 0 deletions AGENTS.md

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions DEVELOPERS.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ To enable a stub Lightning backend so the L2 buttons work without a real node: `
### Faucet (regtest)
The **Faucet** on the Bitcoin page sends sats from the Beacon/Hub wallet to a given address. Regtest only; max 1,000,000 sats per request. Requires the Hub wallet to have balance (e.g. from Generate Block or Beacon epochs). `POST /services/bitcoin/faucet` with body `{ address, amountSats? }`.

### Watch-only xpub HTTP queries (`scantxoutset`)
Public hubs should set **`FABRIC_BITCOIN_XPUB_QUERY_TOKEN`** (or `settings.bitcoin.xpubQueryToken`) to a long random secret. When set, canonical watch-only **`scantxoutset`** endpoints **`GET /services/bitcoin/xpub`**, **`GET /services/bitcoin/xpub/utxos`**, and **`GET /services/bitcoin/xpub/transactions`** (all require **`?xpub=`**), and legacy **`GET /services/bitcoin/wallets/:walletId`** with **`?xpub=`** when `:walletId` is not the Hub’s loaded wallet, return **403** unless the client sends the same token via **`Authorization: Bearer`**, **`?apiToken=`** / **`?xpubQueryToken=`**, or header **`X-Fabric-Xpub-Query-Token`**. Omit the env var for local-only hubs where anonymous xpub scans are acceptable.

## Recent Changes (Contributor Context)

### 1) Payjoin Service Added
Expand Down
3 changes: 2 additions & 1 deletion actions/apiActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ function assertClientFetchPath (input) {
return s;
}

async function fetchFromAPI (path, params = {},token = null) {
async function fetchFromAPI (path, token = null) {
const safe = assertClientFetchPath(path);
const response = await fetch(safe, {
method: 'GET',
Expand Down Expand Up @@ -64,6 +64,7 @@ async function postAPI (path, params, token = null) {
}

module.exports = {
assertClientFetchPath,
fetchFromAPI,
patchAPI,
postAPI
Expand Down
2 changes: 1 addition & 1 deletion actions/bridgeActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const bridgeSync = () => {
const { token } = getState().auth.token;
try {
// TODO: get bridge instance
const instance = await fetchFromAPI(`/`, null, token);
const instance = await fetchFromAPI(`/`, token);
dispatch(bridgeSyncSuccess(instance));
} catch (error) {
dispatch(bridgeSyncFailure(error));
Expand Down
11 changes: 7 additions & 4 deletions actions/chatActions.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use strict';

const fetch = require('cross-fetch');
const { assertClientFetchPath } = require('./apiActions');

// Action Types
const CHAT_REQUEST = 'CHAT_REQUEST';
Expand Down Expand Up @@ -56,7 +57,7 @@
requestBody.file_fabric_id = file_fabric_id;
}

const response = await fetch('/messages', {
const response = await fetch(assertClientFetchPath('/messages'), {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
Expand Down Expand Up @@ -101,7 +102,9 @@
}

try {
const response = await fetch(`/messages/${message.id}`, {
const response = await fetch(
assertClientFetchPath(`/messages/${encodeURIComponent(String(message && message.id != null ? message.id : ''))}`),

Check failure on line 106 in actions/chatActions.js

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

actions/chatActions.js#L106

This application allows user-controlled URLs to be passed directly to HTTP client libraries.
{
method: 'PATCH',
headers: {
'Authorization': `Bearer ${token}`,
Expand Down Expand Up @@ -134,7 +137,7 @@
if (!params.conversation_id) params.conversation_id = state.chat.message.conversation;

try {
const response = await fetch('/messages?' + new URLSearchParams(params), {
const response = await fetch(assertClientFetchPath('/messages?' + new URLSearchParams(params)), {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
Expand Down Expand Up @@ -162,7 +165,7 @@
try {
const state = getState();
const token = state.auth.token;
const response = await fetch('/documents', {
const response = await fetch(assertClientFetchPath('/documents'), {
method: 'SEARCH',
headers: {
// 'Authorization': `Bearer ${token}`,
Expand Down
166 changes: 10 additions & 156 deletions actions/documentActions.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
'use strict';

const { fetchFromAPI } = require('./apiActions');
const { assertClientFetchPath, fetchFromAPI } = require('./apiActions');
const createTimeoutPromise = require('../functions/createTimeoutPromise');
const { safeIdentityErr } = require('../functions/fabricSafeLog');


async function fetchDocumentsFromAPI(token) {
return fetchFromAPI('/documents', null, token);
async function fetchDocumentsFromAPI (token) {
return fetchFromAPI('/documents', token);
}

// Action types
Expand All @@ -18,10 +18,6 @@
const FETCH_DOCUMENT_SUCCESS = 'FETCH_DOCUMENT_SUCCESS';
const FETCH_DOCUMENT_FAILURE = 'FETCH_DOCUMENT_FAILURE';

const FETCH_DOCUMENT_SECTIONS_REQUEST = 'FETCH_DOCUMENT_SECTIONS_REQUEST';
const FETCH_DOCUMENT_SECTIONS_SUCCESS = 'FETCH_DOCUMENT_SECTIONS_SUCCESS';
const FETCH_DOCUMENT_SECTIONS_FAILURE = 'FETCH_DOCUMENT_SECTIONS_FAILURE';

const UPLOAD_DOCUMENT_REQUEST = 'UPLOAD_DOCUMENT_REQUEST';
const UPLOAD_DOCUMENT_SUCCESS = 'UPLOAD_DOCUMENT_SUCCESS';
const UPLOAD_DOCUMENT_FAILURE = 'UPLOAD_DOCUMENT_FAILURE';
Expand All @@ -34,18 +30,6 @@
const CREATE_DOCUMENT_SUCCESS = 'CREATE_DOCUMENT_SUCCESS';
const CREATE_DOCUMENT_FAILURE = 'CREATE_DOCUMENT_FAILURE';

const CREATE_DOCUMENT_SECTION_REQUEST = 'CREATE_DOCUMENT_SECTION_REQUEST';
const CREATE_DOCUMENT_SECTION_SUCCESS = 'CREATE_DOCUMENT_SECTION_SUCCESS';
const CREATE_DOCUMENT_SECTION_FAILURE = 'CREATE_DOCUMENT_SECTION_FAILURE';

const DELETE_DOCUMENT_SECTION_REQUEST = 'DELETE_DOCUMENT_SECTION_REQUEST';
const DELETE_DOCUMENT_SECTION_SUCCESS = 'DELETE_DOCUMENT_SECTION_SUCCESS';
const DELETE_DOCUMENT_SECTION_FAILURE = 'DELETE_DOCUMENT_SECTION_FAILURE';

const EDIT_DOCUMENT_SECTION_REQUEST = 'EDIT_DOCUMENT_SECTION_REQUEST';
const EDIT_DOCUMENT_SECTION_SUCCESS = 'EDIT_DOCUMENT_SECTION_SUCCESS';
const EDIT_DOCUMENT_SECTION_FAILURE = 'EDIT_DOCUMENT_SECTION_FAILURE';

const EDIT_DOCUMENT_REQUEST = 'EDIT_DOCUMENT_REQUEST';
const EDIT_DOCUMENT_SUCCESS = 'EDIT_DOCUMENT_SUCCESS';
const EDIT_DOCUMENT_FAILURE = 'EDIT_DOCUMENT_FAILURE';
Expand All @@ -63,10 +47,6 @@
const fetchDocumentSuccess = (instance) => ({ type: FETCH_DOCUMENT_SUCCESS, payload: instance });
const fetchDocumentFailure = (error) => ({ type: FETCH_DOCUMENT_FAILURE, payload: error });

const fetchDocumentSectionsRequest = () => ({ type: FETCH_DOCUMENT_SECTIONS_REQUEST });
const fetchDocumentSectionsSuccess = (sections) => ({ type: FETCH_DOCUMENT_SECTIONS_SUCCESS, payload: sections });
const fetchDocumentSectionsFailure = (error) => ({ type: FETCH_DOCUMENT_SECTIONS_FAILURE, payload: error });

const uploadDocumentRequest = () => ({ type: UPLOAD_DOCUMENT_REQUEST });
const uploadDocumentSuccess = (fabric_id) => ({ type: UPLOAD_DOCUMENT_SUCCESS, payload: fabric_id });
const uploadDocumentFailure = (error) => ({ type: UPLOAD_DOCUMENT_FAILURE, payload: error });
Expand All @@ -79,18 +59,6 @@
const createDocumentSuccess = (results) => ({ type: CREATE_DOCUMENT_SUCCESS, payload: results });
const createDocumentFailure = (error) => ({ type: CREATE_DOCUMENT_FAILURE, payload: error });

const createSectionRequest = () => ({ type: CREATE_DOCUMENT_SECTION_REQUEST });
const createSectionSuccess = (sections) => ({ type: CREATE_DOCUMENT_SECTION_SUCCESS, payload: sections });
const createSectionFailure = (error) => ({ type: CREATE_DOCUMENT_SECTION_FAILURE, payload: error });

const deleteSectionRequest = () => ({ type: DELETE_DOCUMENT_SECTION_REQUEST });
const deleteSectionSuccess = (sections) => ({ type: DELETE_DOCUMENT_SECTION_SUCCESS, payload: sections });
const deleteSectionFailure = (error) => ({ type: DELETE_DOCUMENT_SECTION_FAILURE, payload: error });

const editSectionRequest = () => ({ type: EDIT_DOCUMENT_SECTION_REQUEST });
const editSectionSuccess = (sections) => ({ type: EDIT_DOCUMENT_SECTION_SUCCESS, payload: sections });
const editSectionFailure = (error) => ({ type: EDIT_DOCUMENT_SECTION_FAILURE, payload: error });

const editDocumentRequest = () => ({ type: EDIT_DOCUMENT_REQUEST });
const editDocumentSuccess = (document) => ({ type: EDIT_DOCUMENT_SUCCESS, payload: document });
const editDocumentFailure = (error) => ({ type: EDIT_DOCUMENT_FAILURE, payload: error });
Expand All @@ -99,8 +67,6 @@
const deleteDocumentSuccess = () => ({ type: DELETE_DOCUMENT_SUCCESS });
const deleteDocumentFailure = (error) => ({ type: DELETE_DOCUMENT_FAILURE, payload: error });



// Thunk action creator
const fetchDocuments = () => {
return async (dispatch, getState) => {
Expand All @@ -120,27 +86,14 @@
dispatch(fetchDocumentRequest());
const { token } = getState().auth.token;
try {
const instance = await fetchFromAPI(`/documents/${encodeURIComponent(fabricID)}`, null, token);
const instance = await fetchFromAPI(`/documents/${encodeURIComponent(fabricID)}`, token);
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
dispatch(fetchDocumentSuccess(instance));
} catch (error) {
dispatch(fetchDocumentFailure(error));
}
};
};

const fetchDocumentSections = (fabric_id) => {
return async (dispatch, getState) => {
dispatch(fetchDocumentSectionsRequest());
const { token } = getState().auth.token;
try {
const sections = await fetchFromAPI(`/documents/sections/${encodeURIComponent(fabric_id)}`, null, token);
dispatch(fetchDocumentSectionsSuccess(sections));
} catch (error) {
dispatch(fetchDocumentSectionsFailure(error));
}
};
};

const uploadDocument = (file) => {
return async (dispatch, getState) => {
dispatch(uploadDocumentRequest());
Expand All @@ -153,7 +106,7 @@
data.append('name', file.name);
data.append('file', file);

const fetchPromise = await fetch('/files', {
const fetchPromise = await fetch(assertClientFetchPath('/files'), {
headers: {
'Authorization': `Bearer ${token}`,
},
Expand Down Expand Up @@ -183,7 +136,7 @@
dispatch(searchDocumentRequest());
const { token } = getState().auth;
try {
const response = await fetch('/documents', {
const response = await fetch(assertClientFetchPath('/documents'), {
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
Expand All @@ -202,13 +155,12 @@
}
}
}
//this starts the document outline, its called in step 2 from document drafter
const createDocument = (type, query) => {
return async (dispatch, getState) => {
dispatch(createDocumentRequest());
const { token } = getState().auth;
try {
const response = await fetch('/documents', {
const response = await fetch(assertClientFetchPath('/documents'), {
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json'
Expand All @@ -231,93 +183,13 @@
}
}

//this creates a new document section, it needs document fabricID, the order number that section will have and its title
//can be called in step 3 when the user, and in the document view edit mode.
const createDocumentSection = (fabricID, target, title, content = null) => {
return async (dispatch, getState) => {
dispatch(createSectionRequest());
const { token } = getState().auth;
try {
const response = await fetch(
`/documents/${encodeURIComponent(fabricID)}/section/${encodeURIComponent(target)}`,
{
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json'
},
method: 'POST',
body: JSON.stringify({ title, content })
});

const sections = await response.json();

dispatch(createSectionSuccess(sections));
} catch (error) {
console.error('Error fetching data:', safeIdentityErr(error));
dispatch(createSectionFailure(error.message));
}
}
}

const deleteDocumentSection = (fabricID, target) => {
return async (dispatch, getState) => {
dispatch(deleteSectionRequest());
const { token } = getState().auth;
try {
const response = await fetch(
`/documents/${encodeURIComponent(fabricID)}/section/delete/${encodeURIComponent(target)}`,
{
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json'
},
method: 'PATCH',
});

const sections = await response.json();

dispatch(deleteSectionSuccess(sections));
} catch (error) {
console.error('Error fetching data:', safeIdentityErr(error));
dispatch(deleteSectionFailure(error.message));
}
}
}

//this edits the document section, first we wont be editing content
const editDocumentSection = (fabricID, target, title, content = null) => {
return async (dispatch, getState) => {
dispatch(editSectionRequest());
const { token } = getState().auth;
try {
const response = await fetch(
`/documents/${encodeURIComponent(fabricID)}/section/${encodeURIComponent(target)}`,
{
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json'
},
method: 'PATCH',
body: JSON.stringify({ title, content })
});

const obj = await response.json();

dispatch(editSectionSuccess(obj));
} catch (error) {
console.error('Error fetching data:', safeIdentityErr(error));
dispatch(editSectionFailure(error.message));
}
}
}

const editDocument = (fabricID,title) => {
const editDocument = (fabricID, title) => {
return async (dispatch, getState) => {
dispatch(editDocumentRequest());
const { token } = getState().auth;
try {
const response = await fetch(
`/documents/${encodeURIComponent(fabricID)}`,
assertClientFetchPath(`/documents/${encodeURIComponent(fabricID)}`),

Check failure on line 192 in actions/documentActions.js

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

actions/documentActions.js#L192

This application allows user-controlled URLs to be passed directly to HTTP client libraries.
{
headers: {
Authorization: `Bearer ${token}`,
Expand All @@ -337,15 +209,13 @@
}
}

//this sets the document status to deleted
//remember to add the last migration
const deleteDocument = (fabricID) => {
return async (dispatch, getState) => {
dispatch(deleteDocumentRequest());
const { token } = getState().auth;
try {
const response = await fetch(
`/documents/delete/${encodeURIComponent(fabricID)}`,
assertClientFetchPath(`/documents/delete/${encodeURIComponent(fabricID)}`),
{
headers: {
Authorization: `Bearer ${token}`,
Expand All @@ -370,13 +240,9 @@
module.exports = {
fetchDocument,
fetchDocuments,
fetchDocumentSections,
uploadDocument,
searchDocument,
createDocument,
createDocumentSection,
deleteDocumentSection,
editDocumentSection,
editDocument,
deleteDocument,
FETCH_DOCUMENT_REQUEST,
Expand All @@ -385,9 +251,6 @@
FETCH_DOCUMENTS_REQUEST,
FETCH_DOCUMENTS_SUCCESS,
FETCH_DOCUMENTS_FAILURE,
FETCH_DOCUMENT_SECTIONS_REQUEST,
FETCH_DOCUMENT_SECTIONS_SUCCESS,
FETCH_DOCUMENT_SECTIONS_FAILURE,
UPLOAD_DOCUMENT_REQUEST,
UPLOAD_DOCUMENT_SUCCESS,
UPLOAD_DOCUMENT_FAILURE,
Expand All @@ -397,15 +260,6 @@
CREATE_DOCUMENT_REQUEST,
CREATE_DOCUMENT_SUCCESS,
CREATE_DOCUMENT_FAILURE,
CREATE_DOCUMENT_SECTION_REQUEST,
CREATE_DOCUMENT_SECTION_SUCCESS,
CREATE_DOCUMENT_SECTION_FAILURE,
DELETE_DOCUMENT_SECTION_REQUEST,
DELETE_DOCUMENT_SECTION_SUCCESS,
DELETE_DOCUMENT_SECTION_FAILURE,
EDIT_DOCUMENT_SECTION_REQUEST,
EDIT_DOCUMENT_SECTION_SUCCESS,
EDIT_DOCUMENT_SECTION_FAILURE,
EDIT_DOCUMENT_REQUEST,
EDIT_DOCUMENT_SUCCESS,
EDIT_DOCUMENT_FAILURE,
Expand Down
2 changes: 1 addition & 1 deletion assets/bundles/browser.min.js

Large diffs are not rendered by default.

Loading
Loading