feat(planning): grille hebdomadaire complète avec API et filtres

- Connexion API via proxy Angular (résolution CORS, base path /api)
- Import CSS ng-zorro global pour les modales et composants
- Filtres Camion/Show câblés sur l'affichage de la grille
- Camions affichés via TrucksService (linkés au show du même créneau)
- Panneau de détails : spectacles + camions du jour sélectionné
- Modale de création de spectacle stylisée avec fond et centrage
- Positionnement précis des events à la minute dans leur créneau
- Auto-scroll vers l'heure courante au chargement
- Ligne "maintenant" sur la colonne du jour actuel
- Régénération des services OpenAPI (nouveaux noms de types)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-27 20:36:03 +02:00
parent 150b97cd2e
commit 654b297e2e
3131 changed files with 149304 additions and 104334 deletions
+1 -1
View File
@@ -13,7 +13,7 @@ A library for generating [Sigstore][1] signatures.
## Prerequisites
- Node.js version ^20.17.0 || >=22.9.0
- Node.js version >= 18.17.0
## Installation
-2
View File
@@ -6,8 +6,6 @@ exports.BaseBundleBuilder = void 0;
// Subclasses must implement the `package` method to assemble a valid bundle
// with the generated signature and verification material.
class BaseBundleBuilder {
signer;
witnesses;
constructor(options) {
this.signer = options.signer;
this.witnesses = options.witnesses;
-1
View File
@@ -21,7 +21,6 @@ const base_1 = require("./base");
const bundle_1 = require("./bundle");
// BundleBuilder implementation for DSSE wrapped attestations
class DSSEBundleBuilder extends base_1.BaseBundleBuilder {
certificateChain;
constructor(options) {
super(options);
this.certificateChain = options.certificateChain ?? false;
-2
View File
@@ -19,8 +19,6 @@ exports.InternalError = void 0;
exports.internalError = internalError;
const error_1 = require("./external/error");
class InternalError extends Error {
code;
cause;
constructor({ code, message, cause, }) {
super(message);
this.name = this.constructor.name;
-2
View File
@@ -17,8 +17,6 @@ limitations under the License.
Object.defineProperty(exports, "__esModule", { value: true });
exports.HTTPError = void 0;
class HTTPError extends Error {
statusCode;
location;
constructor({ status, message, location, }) {
super(`(${status}) ${message}`);
this.statusCode = status;
+2 -2
View File
@@ -19,15 +19,15 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
const promise_retry_1 = require("@gar/promise-retry");
const http2_1 = require("http2");
const make_fetch_happen_1 = __importDefault(require("make-fetch-happen"));
const proc_log_1 = require("proc-log");
const promise_retry_1 = __importDefault(require("promise-retry"));
const util_1 = require("../util");
const error_1 = require("./error");
const { HTTP2_HEADER_LOCATION, HTTP2_HEADER_CONTENT_TYPE, HTTP2_HEADER_USER_AGENT, HTTP_STATUS_INTERNAL_SERVER_ERROR, HTTP_STATUS_TOO_MANY_REQUESTS, HTTP_STATUS_REQUEST_TIMEOUT, } = http2_1.constants;
async function fetchWithRetry(url, options) {
return (0, promise_retry_1.promiseRetry)(async (retry, attemptNum) => {
return (0, promise_retry_1.default)(async (retry, attemptNum) => {
const method = options.method || 'POST';
const headers = {
[HTTP2_HEADER_USER_AGENT]: util_1.ua.getUserAgent(),
-1
View File
@@ -21,7 +21,6 @@ const fetch_1 = require("./fetch");
* Fulcio API client.
*/
class Fulcio {
options;
constructor(options) {
this.options = options;
}
-1
View File
@@ -21,7 +21,6 @@ const fetch_1 = require("./fetch");
* Rekor API client.
*/
class Rekor {
options;
constructor(options) {
this.options = options;
}
+1 -7
View File
@@ -18,18 +18,12 @@ limitations under the License.
*/
const fetch_1 = require("./fetch");
class TimestampAuthority {
options;
constructor(options) {
this.options = options;
}
async createTimestamp(request) {
const { baseURL, timeout, retry } = this.options;
// Account for the fact that the TSA URL may already include the full
// path if the client was initalized from a `SigningConfig` service entry
// (which always uses the full URL).
const url = new URL(baseURL).pathname === '/'
? `${baseURL}/api/v1/timestamp`
: baseURL;
const url = `${baseURL}/api/v1/timestamp`;
const response = await (0, fetch_1.fetchWithRetry)(url, {
headers: {
'Content-Type': 'application/json',
-1
View File
@@ -28,7 +28,6 @@ const providers = [getGHAToken, getEnv];
* one that resolves.
*/
class CIContextProvider {
audience;
/* istanbul ignore next */
constructor(audience = 'sigstore') {
this.audience = audience;
-1
View File
@@ -1,7 +1,6 @@
export type { Bundle } from '@sigstore/bundle';
export { DSSEBundleBuilder, MessageSignatureBundleBuilder } from './bundler';
export type { Artifact, BundleBuilder, BundleBuilderOptions } from './bundler';
export { bundleBuilderFromSigningConfig } from './config';
export { InternalError } from './error';
export { CIContextProvider } from './identity';
export type { IdentityProvider } from './identity';
+1 -3
View File
@@ -1,11 +1,9 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TSAWitness = exports.RekorWitness = exports.DEFAULT_REKOR_URL = exports.FulcioSigner = exports.DEFAULT_FULCIO_URL = exports.CIContextProvider = exports.InternalError = exports.bundleBuilderFromSigningConfig = exports.MessageSignatureBundleBuilder = exports.DSSEBundleBuilder = void 0;
exports.TSAWitness = exports.RekorWitness = exports.DEFAULT_REKOR_URL = exports.FulcioSigner = exports.DEFAULT_FULCIO_URL = exports.CIContextProvider = exports.InternalError = exports.MessageSignatureBundleBuilder = exports.DSSEBundleBuilder = void 0;
var bundler_1 = require("./bundler");
Object.defineProperty(exports, "DSSEBundleBuilder", { enumerable: true, get: function () { return bundler_1.DSSEBundleBuilder; } });
Object.defineProperty(exports, "MessageSignatureBundleBuilder", { enumerable: true, get: function () { return bundler_1.MessageSignatureBundleBuilder; } });
var config_1 = require("./config");
Object.defineProperty(exports, "bundleBuilderFromSigningConfig", { enumerable: true, get: function () { return config_1.bundleBuilderFromSigningConfig; } });
var error_1 = require("./error");
Object.defineProperty(exports, "InternalError", { enumerable: true, get: function () { return error_1.InternalError; } });
var identity_1 = require("./identity");
-1
View File
@@ -19,7 +19,6 @@ limitations under the License.
const error_1 = require("../../error");
const fulcio_1 = require("../../external/fulcio");
class CAClient {
fulcio;
constructor(options) {
this.fulcio = new fulcio_1.Fulcio({
baseURL: options.fulcioBaseURL,
+6 -4
View File
@@ -1,4 +1,7 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.EphemeralSigner = void 0;
/*
@@ -16,21 +19,20 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
const crypto_1 = require("crypto");
const crypto_1 = __importDefault(require("crypto"));
const EC_KEYPAIR_TYPE = 'ec';
const P256_CURVE = 'P-256';
// Signer implementation which uses an ephemeral keypair to sign artifacts.
// The private key lives only in memory and is tied to the lifetime of the
// EphemeralSigner instance.
class EphemeralSigner {
keypair;
constructor() {
this.keypair = (0, crypto_1.generateKeyPairSync)(EC_KEYPAIR_TYPE, {
this.keypair = crypto_1.default.generateKeyPairSync(EC_KEYPAIR_TYPE, {
namedCurve: P256_CURVE,
});
}
async sign(data) {
const signature = (0, crypto_1.sign)('sha256', data, this.keypair.privateKey);
const signature = crypto_1.default.sign(null, data, this.keypair.privateKey);
const publicKey = this.keypair.publicKey
.export({ format: 'pem', type: 'spki' })
.toString('ascii');
-3
View File
@@ -26,9 +26,6 @@ exports.DEFAULT_FULCIO_URL = 'https://fulcio.sigstore.dev';
// Must be instantiated with an identity provider which can provide a JWT
// which represents the identity to be bound to the signing certificate.
class FulcioSigner {
ca;
identityProvider;
keyHolder;
constructor(options) {
this.ca = new ca_1.CAClient({
...options,
+6 -11
View File
@@ -20,16 +20,11 @@ const core_1 = require("@sigstore/core");
function extractJWTSubject(jwt) {
const parts = jwt.split('.', 3);
const payload = JSON.parse(core_1.encoding.base64Decode(parts[1]));
if (payload.email) {
if (!payload.email_verified) {
throw new Error('JWT email not verified by issuer');
}
return payload.email;
}
if (payload.sub) {
return payload.sub;
}
else {
throw new Error('JWT subject not found');
switch (payload.iss) {
case 'https://accounts.google.com':
case 'https://oauth2.sigstore.dev/auth':
return payload.email;
default:
return payload.sub;
}
}
-13
View File
@@ -1,5 +1,3 @@
import type { TransparencyLogEntry } from '@sigstore/bundle';
import type { CreateEntryRequest } from '@sigstore/protobuf-specs/rekor/v2';
import type { Entry, ProposedEntry } from '../../external/rekor';
import type { FetchOptions } from '../../types/fetch';
export type { Entry, ProposedEntry };
@@ -16,14 +14,3 @@ export declare class TLogClient implements TLog {
constructor(options: TLogClientOptions);
createEntry(proposedEntry: ProposedEntry): Promise<Entry>;
}
export interface TLogV2 {
createEntry: (createEntryRequest: CreateEntryRequest) => Promise<TransparencyLogEntry>;
}
export type TLogV2ClientOptions = {
rekorBaseURL: string;
} & FetchOptions;
export declare class TLogV2Client implements TLogV2 {
private rekor;
constructor(options: TLogV2ClientOptions);
createEntry(createEntryRequest: CreateEntryRequest): Promise<TransparencyLogEntry>;
}
+2 -33
View File
@@ -1,8 +1,8 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TLogV2Client = exports.TLogClient = void 0;
exports.TLogClient = void 0;
/*
Copyright 2025 The Sigstore Authors.
Copyright 2023 The Sigstore Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -19,10 +19,7 @@ limitations under the License.
const error_1 = require("../../error");
const error_2 = require("../../external/error");
const rekor_1 = require("../../external/rekor");
const rekor_v2_1 = require("../../external/rekor-v2");
class TLogClient {
rekor;
fetchOnConflict;
constructor(options) {
this.fetchOnConflict = options.fetchOnConflict ?? false;
this.rekor = new rekor_1.Rekor({
@@ -62,31 +59,3 @@ function entryExistsError(value) {
value.statusCode === 409 &&
value.location !== undefined);
}
class TLogV2Client {
rekor;
constructor(options) {
this.rekor = new rekor_v2_1.RekorV2({
baseURL: options.rekorBaseURL,
retry: options.retry,
timeout: options.timeout,
});
}
async createEntry(createEntryRequest) {
let entry;
try {
entry = await this.rekor.createEntry(createEntryRequest);
}
catch (err) {
(0, error_1.internalError)(err, 'TLOG_CREATE_ENTRY_ERROR', 'error creating tlog entry');
}
if (entry.logId === undefined || entry.kindVersion === undefined) {
(0, error_1.internalError)(new Error('invalid tlog entry'), 'TLOG_CREATE_ENTRY_ERROR', 'error creating tlog entry');
}
return {
...entry,
logId: entry.logId,
kindVersion: entry.kindVersion,
};
}
}
exports.TLogV2Client = TLogV2Client;
-2
View File
@@ -1,5 +1,3 @@
import type { CreateEntryRequest } from '@sigstore/protobuf-specs/rekor/v2';
import type { ProposedEntry } from '../../external/rekor';
import type { SignatureBundle } from '../witness';
export declare function toProposedEntry(content: SignatureBundle, publicKey: string, entryType?: 'dsse' | 'intoto'): ProposedEntry;
export declare function toCreateEntryRequest(content: SignatureBundle, publicKey: string): CreateEntryRequest;
+1 -58
View File
@@ -1,9 +1,8 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.toProposedEntry = toProposedEntry;
exports.toCreateEntryRequest = toCreateEntryRequest;
/*
Copyright 2025 The Sigstore Authors.
Copyright 2023 The Sigstore Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -18,7 +17,6 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
const bundle_1 = require("@sigstore/bundle");
const protobuf_specs_1 = require("@sigstore/protobuf-specs");
const util_1 = require("../../util");
const SHA256_ALGORITHM = 'sha256';
function toProposedEntry(content, publicKey,
@@ -140,58 +138,3 @@ function calculateDSSEHash(envelope, publicKey) {
.digest(SHA256_ALGORITHM, util_1.json.canonicalize(dsse))
.toString('hex');
}
function toCreateEntryRequest(content, publicKey) {
switch (content.$case) {
case 'dsseEnvelope':
return toCreateEntryRequestDSSE(content.dsseEnvelope, publicKey);
case 'messageSignature':
return toCreateEntryRequestMessageSignature(content.messageSignature, publicKey);
}
}
function toCreateEntryRequestDSSE(envelope, publicKey) {
return {
spec: {
$case: 'dsseRequestV002',
dsseRequestV002: {
envelope: envelope,
verifiers: [
{
// TODO: We need to add support of passing the key details in the
// signature bundle. For now we're hardcoding the key details here.
keyDetails: protobuf_specs_1.PublicKeyDetails.PKIX_ECDSA_P256_SHA_256,
verifier: {
$case: 'x509Certificate',
x509Certificate: {
rawBytes: util_1.pem.toDER(publicKey),
},
},
},
],
},
},
};
}
function toCreateEntryRequestMessageSignature(messageSignature, publicKey) {
return {
spec: {
$case: 'hashedRekordRequestV002',
hashedRekordRequestV002: {
digest: messageSignature.messageDigest.digest,
signature: {
content: messageSignature.signature,
verifier: {
// TODO: We need to add support of passing the key details in the
// signature bundle. For now we're hardcoding the key details here.
keyDetails: protobuf_specs_1.PublicKeyDetails.PKIX_ECDSA_P256_SHA_256,
verifier: {
$case: 'x509Certificate',
x509Certificate: {
rawBytes: util_1.pem.toDER(publicKey),
},
},
},
},
},
},
};
}
+1 -4
View File
@@ -7,13 +7,10 @@ type TransparencyLogEntries = {
};
export type RekorWitnessOptions = Partial<TLogClientOptions> & {
entryType?: 'dsse' | 'intoto';
majorApiVersion?: number;
};
export declare class RekorWitness implements Witness {
private tlogV1;
private tlogV2;
private tlog;
private entryType?;
private majorApiVersion;
constructor(options: RekorWitnessOptions);
testify(content: SignatureBundle, publicKey: string): Promise<TransparencyLogEntries>;
}
+8 -23
View File
@@ -2,7 +2,7 @@
Object.defineProperty(exports, "__esModule", { value: true });
exports.RekorWitness = exports.DEFAULT_REKOR_URL = void 0;
/*
Copyright 2025 The Sigstore Authors.
Copyright 2023 The Sigstore Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -21,34 +21,17 @@ const client_1 = require("./client");
const entry_1 = require("./entry");
exports.DEFAULT_REKOR_URL = 'https://rekor.sigstore.dev';
class RekorWitness {
tlogV1;
tlogV2;
entryType;
majorApiVersion;
constructor(options) {
this.entryType = options.entryType;
this.majorApiVersion = options.majorApiVersion || 1;
this.tlogV1 = new client_1.TLogClient({
...options,
rekorBaseURL: options.rekorBaseURL || /* istanbul ignore next */ exports.DEFAULT_REKOR_URL,
});
this.tlogV2 = new client_1.TLogV2Client({
this.tlog = new client_1.TLogClient({
...options,
rekorBaseURL: options.rekorBaseURL || /* istanbul ignore next */ exports.DEFAULT_REKOR_URL,
});
}
async testify(content, publicKey) {
let tlogEntry;
if (this.majorApiVersion === 2) {
const request = (0, entry_1.toCreateEntryRequest)(content, publicKey);
tlogEntry = await this.tlogV2.createEntry(request);
}
else {
const proposedEntry = (0, entry_1.toProposedEntry)(content, publicKey, this.entryType);
const entry = await this.tlogV1.createEntry(proposedEntry);
tlogEntry = toTransparencyLogEntry(entry);
}
return { tlogEntries: [tlogEntry] };
const proposedEntry = (0, entry_1.toProposedEntry)(content, publicKey, this.entryType);
const entry = await this.tlog.createEntry(proposedEntry);
return toTransparencyLogEntry(entry);
}
}
exports.RekorWitness = RekorWitness;
@@ -77,7 +60,9 @@ function toTransparencyLogEntry(entry) {
inclusionProof: proof,
canonicalizedBody: Buffer.from(entry.body, 'base64'),
};
return tlogEntry;
return {
tlogEntries: [tlogEntry],
};
}
function inclusionPromise(promise) {
return {
-1
View File
@@ -21,7 +21,6 @@ const tsa_1 = require("../../external/tsa");
const util_1 = require("../../util");
const SHA256_ALGORITHM = 'sha256';
class TSAClient {
tsa;
constructor(options) {
this.tsa = new tsa_1.TimestampAuthority({
baseURL: options.tsaBaseURL,
-1
View File
@@ -18,7 +18,6 @@ limitations under the License.
*/
const client_1 = require("./client");
class TSAWitness {
tsa;
constructor(options) {
this.tsa = new client_1.TSAClient({
tsaBaseURL: options.tsaBaseURL,
+12 -11
View File
@@ -1,6 +1,6 @@
{
"name": "@sigstore/sign",
"version": "4.1.1",
"version": "3.1.0",
"description": "Sigstore signing library",
"main": "dist/index.js",
"types": "dist/index.d.ts",
@@ -27,19 +27,20 @@
},
"devDependencies": {
"@sigstore/jest": "^0.0.0",
"@sigstore/mock": "^0.12.0",
"@sigstore/rekor-types": "^4.0.0",
"@types/make-fetch-happen": "^10.0.4"
"@sigstore/mock": "^0.10.0",
"@sigstore/rekor-types": "^3.0.0",
"@types/make-fetch-happen": "^10.0.4",
"@types/promise-retry": "^1.1.6"
},
"dependencies": {
"@sigstore/bundle": "^4.0.0",
"@sigstore/core": "^3.2.0",
"@sigstore/protobuf-specs": "^0.5.0",
"make-fetch-happen": "^15.0.4",
"proc-log": "^6.1.0",
"@gar/promise-retry": "^1.0.2"
"@sigstore/bundle": "^3.1.0",
"@sigstore/core": "^2.0.0",
"@sigstore/protobuf-specs": "^0.4.0",
"make-fetch-happen": "^14.0.2",
"proc-log": "^5.0.0",
"promise-retry": "^2.0.1"
},
"engines": {
"node": "^20.17.0 || >=22.9.0"
"node": "^18.17.0 || >=20.5.0"
}
}