365) {
$errors[] = 'Duration must be between 1 and 365 days.';
}
if ($errors) {
return '
'
. '
Signal registered successfully. '
. 'A Verifiable Credential will be issued and timestamped to Bitcoin.
'
. '
← Back to Value Layer
'
. '
';
}
return ''
. '
Signal could not be registered. '
. 'The orchestrator may be temporarily unavailable. Please try again.
'
. '
'
. cry01_render_signal_form($association_slug, $access);
}
// ---------------------------------------------------------------------------
// MANAGE POST HANDLER
// ---------------------------------------------------------------------------
function cry01_handle_manage_post($association_slug) {
// Handles operator manage actions.
if (!cry01_verify_csrf()) {
return cry01_render_error('Invalid form token. Please reload and try again.');
}
$action = $_POST['action'] ?? '';
if ($action === 'refresh_cache') {
// The public key comes from the wallet session via the hidden form field.
// It is never read from config — the operator is a participant like any other.
$g1_pubkey = trim($_POST['g1_pubkey'] ?? '');
if (!$g1_pubkey) {
return ''
. '
No Ğ1 public key received. '
. 'Unlock your
Ğ1 Wallet first, then try again.
'
. '
'
. cry01_render_manage($association_slug);
}
$ok = cry01_refresh_balance_cache($g1_pubkey);
$msg = $ok
? 'Balance cache refreshed successfully.
'
: 'Cache refresh failed. Check that the Duniter node is reachable.
';
return '' . $msg . '
' . cry01_render_manage($association_slug);
}
return cry01_render_error('Unknown action.');
}
// ---------------------------------------------------------------------------
// ORCHESTRATOR TRANSPORT
// ---------------------------------------------------------------------------
function cry01_post_to_orchestrator($path, $payload) {
// POSTs a JSON envelope to the orchestrator spool receiver.
// Returns true on success (HTTP 201), false on any failure.
$config = cry01_load_config();
$base = rtrim($config['receiver_url'] ?? '', '/');
if (!$base) {
logger('cry01_spool: receiver_url not configured');
return false;
}
$url = $base . $path;
$body = json_encode($payload);
$context = stream_context_create([
'http' => [
'method' => 'POST',
'header' => "Content-Type: application/json\r\nContent-Length: " . strlen($body) . "\r\n",
'content' => $body,
'timeout' => 10,
'ignore_errors' => true,
],
]);
$raw = @file_get_contents($url, false, $context);
$headers = $http_response_header ?? [];
$status = 0;
foreach ($headers as $h) {
if (preg_match('/HTTP\/\d\.\d\s+(\d+)/', $h, $m)) {
$status = intval($m[1]);
}
}
if ($status === 201) return true;
logger('cry01_spool: orchestrator returned status ' . $status . ' for ' . $path);
return false;
}