Configuration

This document describes the settings specific to RestFrontage and the GraphicStream libraries that it initializes.

Standard ASP.NET Core topics, such as Logging, AllowedHosts or the choice of hosting environment, are not detailed. They are the appanage of the underlying system to ASP.Net and IIS.

1. Overview

Section Status Role
Database Required Chooses SQL Server LocalDB, SQLite, or remote SQL Server and names the local business and security databases.
ConnectionStrings Required in remote SQL Server mode Configures business, security, server, and licensing basics.
LogsSettings Required Configures the GraphicStream logger and log destination.
IOSettings Required in practice Configures media and file storage.
Application Required Configures server identity, tokens, empty passwords, warm-up, and task loop.
Application:OpenAI Conditional Configures AI functions using Azure OpenAI Assistants.
Environment Optional Displays a banner to visually identify the environment.
SecurityDomainSynchronization Optional Regulates the synchronization of the security domain between instances.
Recovery Recommended Protects the recovery console independent of the security base.
ApiKey Conditional Declares API keys associated with Immersive users.
Saml Conditional Configures SAML authentication with FID.
OpenID Conditional Configures OpenID token validation with the FID.
Session Optional Activates the server session only when the section contains at least one parameter. An absent or empty section maintains sessionless operation.
IPX Inactive The section IPX:Export of the provided file is not read by any component.

2. Selecting the Database Mode

RestFrontage enforces this priority:

  1. Database:EnableLocalDB = true selects SQL Server LocalDB;
  2. otherwise, Database:EnableSqlite = true selects SQLite;
  3. otherwise, RestFrontage uses the SQL Server strings of ConnectionStrings.

2.1 Remote SQL Server or SQL Server Express

Recommended minimum requirements for a full deployment:

{
  "Database": {
    "EnableLocalDB": false,
    "EnableSqlite": false
  },
  "ConnectionStrings": {
    "ImmersiveModelContainer": "<chaine SQL de la base metier>",
    "SecurityModelContainer": "<chaine SQL de la base de securite>",
    "ServerDatabaseContext": "<chaine SQL des donnees serveur>",
    "LicenseModelContainer": "<chaine SQL des licences>"
  }
}

Key Required Use and Fall
ImmersiveModelContainer Yes Immersive business data. Also serves as a fallback to ServerDatabaseContext.
SecurityModelContainer Yes Users, groups, rights, and security domain. Also serves as a fallback for LicenseModelContainer.
ServerDatabaseContext No Server tasks and internal AI data. IPX history and work sessions also use this connection. With no value or if not specified, the business base is used.
LicenseModelContainer No Installed licenses. With no value or if not specified, the security base is used.

In SQL Server mode, access to the business, security, server, license, and IPX history enables up to five retries on transient SQL errors, with a maximum delay of ten seconds between retries.

The log database is not configured in ConnectionStrings. It uses exclusively LogsSettings:ConnectionString.

2.2 SQLite

{
  "Database": {
    "EnableLocalDB": false,
    "EnableSqlite": true,
    "ImmersiveSqlite": "Immersive.sqlite",
    "ImmersiveSecuritySqlite": "ImmersiveSecurity.sqlite"
  },
  "LogsSettings": {
    "ConnectionString": "ImmersiveLogs.sqlite"
  }
}

Key Role
ImmersiveSqlite Business database and storage of IPX history.
ImmersiveSecuritySqlite Security base.

LogsSettings:ConnectionString contains the name or relative path of the SQLite log file here. Both the logger and the lookup context use the same file.

The SQLite paths are resolved relative to the folder containing the RestFrontage executable and the files must already exist. The current code does not create the missing SQLite files.

2.3 SQL Server LocalDB

{
  "Database": {
    "EnableLocalDB": true,
    "EnableSqlite": false,
    "ImmersiveDatabaseName": "Immersive",
    "ImmersiveSecurityDatabaseName": "ImmersiveSecurity",
    "ImmersiveBacPacName": "Immersive.bacpac",
    "ImmersiveSecurityBacPacName": "ImmersiveSecurity.bacpac",
    "ImmersiveLogBacPacName": "ImmersiveLogs.bacpac"
  },
  "LogsSettings": {
    "ConnectionString": "ImmersiveLogs"
  }
}

Key Required Role
ImmersiveDatabaseName Yes File Name <nom>.mdf and the business base.
ImmersiveSecurityDatabaseName Yes The name of the file and the security database.
ImmersiveBacPacName No BACPAC initial of the business base.
ImmersiveSecurityBacPacName No BACPAC of the safety base.
ImmersiveLogBacPacName No BACPAC database of newspapers whose name is given by LogsSettings:ConnectionString.

LogsSettings:ConnectionString contains the logical name of the LocalDB log database here, without extension .mdf not a full SQL string. In the example, RestFrontage opens or creates ImmersiveLogs.mdf, and then the logger and the lookup context reuse the LocalDB string that was actually obtained.

MDF files are placed in the subfolder Data located next to the assemblies. When creating a database, a BACPAC is searched under Assets/Bacpac.

This mode requires SQL Server LocalDB on the machine. As in SQLite mode, the current code does not save ServerDatabaseContext nor LicenseSecurityModel.

2.4 A single destination for logs

The destination of the logs is always defined by LogsSettings:ConnectionString. RestFrontage automatically interprets its value according to the mode chosen under Database :

Fashion Expected value in LogsSettings:ConnectionString Resolution Completed
Remote SQL Server The full SQL Server connection string. The string is used as is.
SQL Server LocalDB Logical name of the database, for example ImmersiveLogs. RestFrontage opens or creates the file <nom>.mdf, and then constructs the LocalDB string.
SQLite For example, the relative name or path of the file ImmersiveLogs.sqlite. RestFrontage checks the file next to the executable and builds the SQLite connection.

This resolution is common to both uses: the batch logger that writes the messages and the context LogsContext who consults them. They can therefore no longer point involuntarily to two different bases.

3. GraphicStream Logs – LogsSettings

The GraphicStream logger writes the logs in the background so that it does not open a connection for each message. When a message is produced, it is placed in a queue in memory. At regular intervals, the logger picks up a group of messages from this queue and inserts it into the selected database.

The settings in this section define four elements: the destination, the identification of the producer tool, the capacity of the queue, and how messages are grouped and then retained.

{
  "LogsSettings": {
    "ProviderIdentifier": 10,
    "IncludeScopes": true,
    "IsEnabled": true,
    "ContainerName": "Log",
    "ConnectionString": "<chaine SQL de la base des journaux>",
    "FlushPeriod": "00:00:01",
    "BackgroundQueueSize": 1000,
    "BatchSize": null,
    "TableSizeLimit": 10240
  }
}

Key Default Real effect and parameterization tips
ConnectionString none The unique destination of the logger and the consultation context. In remote SQL Server, fill in a complete SQL string; in LocalDB, the logical name of the database; in SQLite, the relative name or path of the file. The value is independent of the section ConnectionStrings.
ContainerName Log The name of the table receiving the logs. The recommended value is Log, which corresponds to the schema provided by GraphicStream.
ProviderIdentifier 0 Allows you to differentiate between the different tools that inject into the Log, to share the same log database across multiple GraphicStream tools, such as multiple RestFrontage and/or Hubs.
IncludeScopes true Allows the reading of structured information placed in the logging scopes. The logger recognizes in particular Channel, which classifies the message into a channel, and Data, which adds additional data. Without a channel provided, the message is stored in the channel Generic.
IsEnabled true Enables the GraphicStream log provider. À false, its processing queue is stopped, and new messages are not logged by this provider. This setting does not necessarily disable any other log destinations that may be configured.
FlushPeriod 00:00:01 The amount of time to wait between two write cycles. With one second, pending messages are sent to the database approximately every second. A shorter value reduces the time it takes to appear in the database but increases the frequency of hits; a longer value groups more writes but delays their visibility. The duration must be strictly positive.
BackgroundQueueSize 1000 The maximum number of messages that can wait in memory before they are processed. When the bounded queue is full, the producer waits for a place to become available, so a value that is too low can slow down requests during an influx of logs. null Creates a limitless queue, at the cost of potentially higher memory consumption. Use a strictly positive value. 0 is accepted by the option class but does not allow the queue to be built at runtime.
BatchSize null The maximum number of messages that are removed from the queue and inserted in a cycle. null processes all available messages. A positive value limits the size of each batch; if the queue contains more messages, the rest waits for subsequent cycles. A value that is too low can cause a delay when a lot of logs are produced.
TableSizeLimit 10240 The maximum number of rows kept. After a batch is written, the logger deletes the oldest entries, according to their date, to fall below this limit. null deactivates this automatic purge. A value entered must be strictly positive.

Example of how to work with the above values: up to 1,000 messages can wait in the queue; approximately every second, all available messages are written in batches since BatchSize is worth null ; After writing, the oldest logs are deleted if the table exceeds 10,240 rows.

Storage should not be manually chosen for RestFrontage. The application forces it to SQL for remote SQL Server and LocalDB, or SQLite when Database:EnableSqlite is enabled. Any value Storage present in the JSON is therefore replaced by this calculated choice.

FileSizeLimit, RetainedFileCountLimit, FileName and Extension exist in the option class, but are not used by the SQL Server and SQLite providers selected by RestFrontage.

The levels under Logging and Logging:GraphicStreamLogs:LogLevel are part of standard log filtering and are not detailed here.

4. File Storage – IOSettings

{
  "IOSettings": {
    "Storage": "AzureBlob",
    "ConnectionString": "<secret ou chemin selon le mode>",
    "ContainerName": "immersivecontent"
  }
}

Storage ConnectionString ContainerName
AzureBlob The connection string of the Azure Storage account. Container Name: Blob.
FileSystem The root folder of the storage. Subfolder added to the root.
HostEnvironment Ignored. A subfolder of the RestFrontage root directory.
SQL The SQL Server connection string. The name of the table that includes the path and binary content.

A change requires a restart to be applied consistently.

Pros HostEnvironment, all operations use the same root: ContentRootPath, that is, the root directory of RestFrontage. The existence test, read, write, list, and delete are all targeting <ContentRootPath>/<ContainerName>/<chemin> ; ConnectionString is ignored in this mode.

5. General RestFrontage Settings – Application

{
  "Application": {
    "Name": "RestFrontage PROD",
    "AllowBlankPassword": false,
    "PreWarmOrganizations": [ "Organisation A" ],
    "TokenLifetime": "08:00:00",
    "JWTSecurityKey": "<secret aleatoire d'au moins 32 octets>",
    "TaskManagerLoopIdleTime": 60
  }
}

Key Default Real effect
Name null Name returned by the system API; visible fallback: ImmersiveRest Server.
AllowBlankPassword false Allows authentication with a blank password and influences initialization auditing. Leave to false in production.
PreWarmOrganizations null The names of organizations whose caches are preloaded at startup. An empty array retains on-demand loading.
TokenLifetime 08:00:00 Duration of JWTs emitted by RestFrontage.
JWTSecurityKey None reliable HMAC secret used to sign and validate JWTs. It must exceed 256 bits, remain the same between instances, and never be committed. Changing it invalidates existing tokens.
TaskManagerLoopIdleTime 60 Pause, in seconds, between two passes in the server task loop. Use a strictly positive value.

The section Application Must exist: The linked application is then requested as a required service during initialization.

6. Azure OpenAI – Application:OpenAI

{
  "Application": {
    "OpenAI": {
      "Endpoint": "https://<ressource>.openai.azure.com",
      "ApiKey": "<secret>",
      "AssistantName": "asst_<identifiant>",
      "APIVersion": "2024-05-01-preview"
    }
  }
}

Key Mandatory for AI Role
Endpoint Yes The URL of the Azure OpenAI resource. The final slash is removed by the service.
ApiKey Yes Value sent in the header api-key.
AssistantName Yes Despite its name, this value must be the technical identifier of the wizard, for example asst_....
APIVersion No Azure OpenAI API version; default 2024-05-01-preview.

The absence of this subsection does not prevent startup; the error is thrown the first time an AI function is called that requires these values.

7. Visual identification - Environment

{
  "Environment": {
    "Name": "PROD",
    "BackgroundColor": "#B00020",
    "ForegroundColor": "#FFFFFF",
    "Size": 6
  }
}

Key Default Role
Name empty Text displayed on the reception desk and in the breadcrumb trail. Without a name, the welcome badge is hidden.
BackgroundColor #333 The background CSS color of the environment guide.
ForegroundColor white CSS color of the text.
Size 7 Bootstrap Class Suffix fs-{Size} in breadcrumbs. Use a valid Bootstrap value of 1 à 6.

This section describes a RestFrontage visual cue; it is separate from the hosting environment name ASP.NET Core.

8. Security Synchronization – SecurityDomainSynchronization

{
  "SecurityDomainSynchronization": {
    "VersionCheckInterval": "00:00:01"
  }
}

VersionCheckInterval is the interval between two reads of the distributed version of the security domain. When another instance publishes a new version, RestFrontage reloads its local domain.

The default value is one second. A zero or negative duration is replaced by a second.

All instances sharing the same databases must use a consistent interval. A very short value reduces propagation delay but increases distributed cache hits.

9. Recovery Console – Recovery

{
  "Recovery": {
    "AccessKey": "<secret long et aleatoire>"
  }
}

AccessKey protects the page /Setup/Tools, designed to remain accessible even when the security base fails. Without a key, the console cannot be unlocked. After validation, access is retained in a signed cookie for 30 minutes.

The dedicated environment variable IMMERSIVE_RECOVERY_KEY takes precedence over Recovery:AccessKey and must be prioritized in production.

Case of Recovery Overloads

A Recovery Overhead is a fallback configuration value that temporarily replaces the normal value with the same name. It is used to repair a server with a misconfigured connection, logs, or storage, without directly modifying the file appsettings.json original.

The console /Setup/Tools saves these values in the optional file appsettings.Recovery.json, placed in the root directory of RestFrontage. For example, if this file contains a new value for ConnectionStrings:ImmersiveModelContainer, this value replaces the value of appsettings.json at the next boot. Other keys that are not in the recovery file continue to come from the normal configuration.

The console can create or complete the following sections:

  • The four recognized chains of ConnectionStrings ;
  • LogsSettings ;
  • IOSettings.

The recovery file therefore functions as a partial layer overlaid on top of the existing configuration:

  1. appsettings.json and other usual configuration files provide normal values;
  2. appsettings.Recovery.json Replaces only the keys it contains.
  3. Environment variables and launch arguments still take precedence over both files.

Example:

{
  "ConnectionStrings": {
    "ImmersiveModelContainer": "<chaine SQL de remplacement>"
  },
  "IOSettings": {
    "Storage": "FileSystem",
    "ConnectionString": "D:\\ImmersiveData",
    "ContainerName": "Content"
  }
}

In this example, only the business base and the IOSettings are overloaded. The security baseline, licenses, logs, and all other settings maintain their normal values.

10. API Key Authentication - ApiKey

{
  "ApiKey": [
    {
      "App": "Forge",
      "Key": "<secret>",
      "User": "AN=ServiceForge, OU=Users, DC=Immersive, DC=GraphicStream, DC=fr",
      "From": "2026-01-01T00:00:00Z",
      "To": "2027-01-01T00:00:00Z"
    }
  ]
}

Key Rule
App Expected value in the header x-app-name. The comparison ignores case. An empty value disables the input.
Key Expected value in x-api-key. The comparison is case-sensitive. An empty value disables the input.
User The exact distinguished name of an existing user in the security database. This user becomes the identity of the query.
From Beginning of validity included.
To Purpose excluded from validity.

Use ISO 8601 dates with time zone, ideally in UTC with the suffix Z. The duration of the internal JWT created for the request is limited to the time remaining before To.

11. SAML - Saml

{
  "Saml": {
    "FidUrl": "https://<fid>",
    "FidSsoPath": "/<chemin-sso>",
    "FidSloPath": "/<chemin-slo>",
    "EntityId": "<identifiant RestFrontage declare dans la FID>",
    "LoginUrl": "https://<restfrontage>/api/Saml/Login",
    "LogoutUrl": "https://<restfrontage>/api/Saml/Logout"
  }
}

Key Role
FidUrl The base URL of the identity federation.
FidSsoPath Path added to FidUrl to construct the SAML connection request.
FidSloPath Path added to FidUrl to construct the SAML logout request.
EntityId The sender declared in SAML requests.
LoginUrl Absolute connection return URL, placed in AssertionConsumerServiceURL.
LogoutUrl Absolute logout return URL.

12. OpenID – OpenID

{
  "OpenID": {
    "FidUrl": "https://<fid>/",
    "FidAppId": "<client-id>",
    "FidAppSecret": "<secret>"
  }
}

Key Real effect
FidUrl Base URL used to invoke relative paths tokeninfo and userinfo. Keep a final slash.
FidAppId Must match the client_id Returned by tokeninfo.
FidAppSecret Is loaded into the service, but is not currently sent in any OpenID controller calls.

13. Session

The server session is now Optional. RestFrontage activates it only if the Session contains at least one parameter: Session services are then registered and session middleware is added after routing.

If the section is missing or empty, RestFrontage does not register any session service and does not add the corresponding middleware. This means that the operation remains the same as before conditional activation.

{
  "Session": {
    "IdleTimeout": "01:00:00",
    "Cookie": {
      "Name": "Immersive.Server.Session",
      "HttpOnly": true,
      "SameSite": "Strict",
      "SecurePolicy": "Always"
    }
  }
}

Key Role
IdleTimeout The maximum amount of time that session data is idle. An activity using the session extends this time.
Cookie:Name The name of the technical cookie containing the session ID.
Cookie:HttpOnly Prevents the browser's JavaScript from reading the session cookie. Keep true.
Cookie:SameSite Controls the sending of the cookie when browsing from another site. Strict is the most restrictive setting.
Cookie:SecurePolicy With Always, the cookie is only sent over HTTPS.

Session uses the IDistributedCache already stored by RestFrontage. The cookie does not contain session data: it only contains an identifier that can be used to retrieve this data in the distributed cache.

To explicitly keep the historical operation without a session, delete the section entirely or leave it blank:

{
  "Session": {}
}

The recognized keys are:

  • Session:IdleTimeout ;
  • Session:Cookie:Name ;
  • Session:Cookie:HttpOnly ;
  • Session:Cookie:SameSite ;
  • Session:Cookie:SecurePolicy.

14. Secrets Management

The appsettings file contains values that can be real SQL passwords, an Azure Storage account key, an Azure OpenAI key, and a JWT key. They are purposely not reproduced in this documentation.

If these values are active or have been committed, they must be renewed regularly. At a minimum, the following must be outsourced:

  • ConnectionStrings__ImmersiveModelContainer ;
  • ConnectionStrings__SecurityModelContainer ;
  • ConnectionStrings__ServerDatabaseContext ;
  • ConnectionStrings__LicenseModelContainer ;
  • LogsSettings__ConnectionString ;
  • IOSettings__ConnectionString ;
  • Application__JWTSecurityKey ;
  • Application__OpenAI__ApiKey ;
  • OpenID__FidAppSecret ;
  • ApiKey__0__Key, and then the following indexes;
  • IMMERSIVE_RECOVERY_KEY.

15. Sample Cleaned Production

This example groups together the useful RestFrontage settings without the standard Core ASP.NET topics:

{
  "Database": {
    "EnableLocalDB": false,
    "EnableSqlite": false
  },
  "ConnectionStrings": {
    "ImmersiveModelContainer": "<injecte hors du fichier>",
    "SecurityModelContainer": "<injecte hors du fichier>",
    "ServerDatabaseContext": "<injecte hors du fichier>",
    "LicenseModelContainer": "<injecte hors du fichier>"
  },
  "Environment": {
    "Name": "PROD",
    "BackgroundColor": "#B00020",
    "ForegroundColor": "#FFFFFF",
    "Size": 6
  },
  "Recovery": {
    "AccessKey": "<injecte via IMMERSIVE_RECOVERY_KEY>"
  },
  "SecurityDomainSynchronization": {
    "VersionCheckInterval": "00:00:01"
  },
  "LogsSettings": {
    "ProviderIdentifier": 10,
    "IncludeScopes": true,
    "IsEnabled": true,
    "ContainerName": "Log",
    "ConnectionString": "<injecte hors du fichier>"
  },
  "IOSettings": {
    "Storage": "AzureBlob",
    "ConnectionString": "<injecte hors du fichier>",
    "ContainerName": "immersivecontent"
  },
  "Application": {
    "Name": "RestFrontage PROD",
    "AllowBlankPassword": false,
    "PreWarmOrganizations": [],
    "TokenLifetime": "08:00:00",
    "JWTSecurityKey": "<injecte hors du fichier>",
    "TaskManagerLoopIdleTime": 60,
    "OpenAI": {
      "Endpoint": "https://<ressource>.openai.azure.com",
      "ApiKey": "<injecte hors du fichier>",
      "AssistantName": "asst_<identifiant>",
      "APIVersion": "2024-05-01-preview"
    }
  },
  "ApiKey": [],
  "Saml": {
    "FidUrl": "https://<fid>",
    "FidSsoPath": "/<chemin-sso>",
    "FidSloPath": "/<chemin-slo>",
    "EntityId": "<entity-id>",
    "LoginUrl": "https://<restfrontage>/api/Saml/Login",
    "LogoutUrl": "https://<restfrontage>/api/Saml/Logout"
  },
  "OpenID": {
    "FidUrl": "https://<fid>/",
    "FidAppId": "<client-id>",
    "FidAppSecret": "<injecte hors du fichier>"
  }
}

Subsections OpenAI, ApiKey, Saml and OpenID can be omitted when the corresponding functions are not used.

16. Pre-commissioning inspection

  • Only one basic mode is enabled.
  • The channels have exactly the expected names.
  • The log database is configured in LogsSettings:ConnectionString.
  • JWTSecurityKey is random, long enough, and the same across all instances.
  • AllowBlankPassword is worth false in production.
  • No real secrets are stored in a versioned file.
  • Organizations from PreWarmOrganizations really exist.
  • API keys have an application, a key, an existing user, and a valid time period.
  • SAML contains both paths well FidSsoPath and FidSloPath.
  • Values ??? were overridden before enabling SAML or OpenID.
  • The section Session is absent or empty if no server session is desired; otherwise its cookie is set to HTTPS.
  • RestFrontage was restarted after a change in connection, storage, logs, or JWT secret.