`taskstream: true` on POST /v1/projects also creates the project in TaskStream, public, as the caller (their Pireon token is passed on), and the answer carries `taskstream_key` and `taskstream_url`. The key is `taskstream_key` or one made from the default-language slug. The board is opened before the project is saved: if TaskStream refuses it, nothing is created here and the reason comes back as a validation error (502 when TaskStream does not answer). Machine tokens need the server's own TASKSTREAM_TOKEN. Updates ignore the flag, and duplicates do not inherit the link. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
42 lines
1.0 KiB
PHP
42 lines
1.0 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Services\TaskStream;
|
|
|
|
use RuntimeException;
|
|
use Throwable;
|
|
|
|
class TaskStreamException extends RuntimeException
|
|
{
|
|
public function __construct(
|
|
string $message,
|
|
public readonly ?int $status = null,
|
|
?Throwable $previous = null,
|
|
) {
|
|
parent::__construct($message, $status ?? 0, $previous);
|
|
}
|
|
|
|
/**
|
|
* TaskStream refused what it was asked for (a key in use, a bad name):
|
|
* the caller can fix it and try again.
|
|
*/
|
|
public function isRefusal(): bool
|
|
{
|
|
return in_array($this->status, [400, 409, 422], true);
|
|
}
|
|
|
|
/**
|
|
* The token was not good enough there: expired, or without access.
|
|
*/
|
|
public function isUnauthorised(): bool
|
|
{
|
|
return in_array($this->status, [401, 403], true);
|
|
}
|
|
|
|
public static function unreachable(string $url, ?Throwable $previous = null): self
|
|
{
|
|
return new self("TaskStream could not be reached at [{$url}].", previous: $previous);
|
|
}
|
|
}
|