Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
117 changes: 117 additions & 0 deletions PRIVACY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
# Captail Privacy Policy

Effective date: August 3, 2026

This policy applies to the Captail desktop application and its official
Microsoft Store and GitHub distributions.

## Summary

Captail records instant replays locally on your Windows PC. Captail does not
sell personal information, include advertising or analytics, automatically
upload recordings, or provide the developer with access to your captures.

## Information processed locally

Depending on the features you enable, Captail may process:

- desktop, application, or game video frames;
- desktop or game audio;
- microphone audio;
- monitor, audio-device, GPU, codec, and game-process information needed to
configure capture;
- replay files and their technical metadata;
- settings such as hotkeys, selected devices, and output folders.

This information is processed on your device to maintain the replay buffer,
save clips, organize recordings, show previews, and trim saved videos. Captail
does not transmit captured video or audio to the developer or to a Captail
cloud service.

Captail does not attempt to bypass DRM or protected-media restrictions.
Protected content may appear black or unavailable in recordings.

## Local storage

Saved replays are written to the folder you select. The rolling replay buffer
is held locally and only becomes a normal video file when you save a replay.

Captail stores configuration and diagnostic logs under its local application
data. The logical log location is:

```text
%LOCALAPPDATA%\Captail\log.txt
```

Windows may map Store-package application data to a package-specific location.
Logs can contain technical errors, device and GPU names, codec settings, game
or process names, and local file paths. Logs do not intentionally contain raw
video frames or recorded audio. Logs are not uploaded automatically. Review
them and remove sensitive paths or names before attaching them to a public bug
report.

## Network access

Captail has no telemetry, analytics, advertising, account, or cloud-storage
service.

The Microsoft Store build relies on Microsoft Store for application updates
and does not check GitHub Releases for updates. Microsoft Store may process
installation, licensing, update, and diagnostic information under Microsoft's
own privacy terms.

Installer and Portable builds distributed through GitHub may contact the
GitHub Releases API to check for and download updates. Those requests identify
the Captail version and necessarily expose network information such as the IP
address to GitHub. GitHub processes that information under the
[GitHub Privacy Statement](https://docs.github.com/en/site-policy/privacy-policies/github-general-privacy-statement).

Opening a GitHub, support, or repository link from Captail launches your
default web browser. The destination website then applies its own privacy
policy.

## Permissions

Captail uses only permissions needed for its recording workflow, including:

- screen and game capture;
- system-audio and optional microphone capture;
- global replay hotkeys;
- access to folders selected for replay storage;
- hardware encoder detection;
- optional startup with Windows.

Microphone recording and startup with Windows can be disabled in Captail's
settings. Capture can be stopped at any time by turning Instant Replay off or
exiting Captail.

## Sharing and disclosure

Captail does not sell or share local recordings, settings, or diagnostic logs.
Information leaves your device only when you choose to share a replay or log,
or when a non-Store build performs the GitHub update request described above.

## Retention and deletion

You control saved replay retention. Replays can be deleted from Captail or
Windows File Explorer. Configuration and logs remain locally until you delete
them or Windows removes the application's data. Uninstalling Captail does not
guarantee removal of replay files stored in your chosen output folder.

## Children's privacy

Captail is a general-purpose recording utility and is not directed to children.
The developer does not knowingly collect personal information from children.

## Changes to this policy

Material changes will be published in this file and recorded in the
repository's Git history. The effective date above will be updated when the
policy changes.

## Contact

For privacy questions, open an issue in the
[Captail repository](https://github.com/FaulMit/captail/issues). Do not include
recordings, logs, local paths, or other sensitive information in a public
issue.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,8 @@ Read [CONTRIBUTING.md](CONTRIBUTING.md) before submitting changes. Release maint

Captail is licensed under [GNU GPL-2.0-or-later](LICENSE).

Privacy details are documented in [PRIVACY.md](PRIVACY.md).

Captail uses libobs and selected OBS Studio runtime components. See [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md).

Captail is not affiliated with or endorsed by NVIDIA or OBS Project. NVIDIA and ShadowPlay are trademarks of NVIDIA Corporation.
15 changes: 15 additions & 0 deletions docs/RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,18 @@ Output is written to `artifacts\release\0.1.1`.
- Major: breaking change (`0.x` → `1.0.0`)

Never replace published binaries under an existing tag. Publish a new version.

## Microsoft Store release

Microsoft Store is a separate package channel. It must not be attached to a
GitHub Release because Store installs, signs, and updates the package.

Build an upload-ready package locally:

```powershell
.\tools\BuildStorePackage.ps1 -Version 0.1.5
```

Upload `artifacts\store\0.1.5\Captail-0.1.5.0-x64.msixupload` in Partner
Center. Full identity, validation, update-channel, and submission instructions
are in [`packaging/msix/README.md`](../packaging/msix/README.md).
61 changes: 61 additions & 0 deletions packaging/msix/AppxManifest.xml.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="utf-8"?>
<Package
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:uap10="http://schemas.microsoft.com/appx/manifest/uap/windows10/10"
xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10"
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
IgnorableNamespaces="uap uap10 desktop rescap">
<Identity
Name="faulmit.Captail"
Publisher="CN=1BD9448E-C83F-401D-B530-ED5258C6319A"
Version="__PACKAGE_VERSION__"
ProcessorArchitecture="x64" />
<Properties>
<DisplayName>Captail</DisplayName>
<PublisherDisplayName>faulmit</PublisherDisplayName>
<Description>Lightweight instant replay recorder for Windows.</Description>
<Logo>Assets\StoreLogo.png</Logo>
</Properties>
<Resources>
<Resource Language="en-us" />
<Resource Language="ru-ru" />
</Resources>
<Dependencies>
<TargetDeviceFamily
Name="Windows.Desktop"
MinVersion="10.0.19041.0"
MaxVersionTested="10.0.26100.0" />
</Dependencies>
<Applications>
<Application
Id="Captail"
Executable="Captail.exe"
uap10:RuntimeBehavior="packagedClassicApp"
uap10:TrustLevel="mediumIL">
<uap:VisualElements
DisplayName="Captail"
Description="Lightweight instant replay recorder for Windows."
BackgroundColor="transparent"
Square150x150Logo="Assets\Square150x150Logo.png"
Square44x44Logo="Assets\Square44x44Logo.png">
<uap:DefaultTile ShortName="Captail" />
</uap:VisualElements>
<Extensions>
<desktop:Extension
Category="windows.startupTask"
Executable="Captail.exe"
EntryPoint="Windows.FullTrustApplication">
<desktop:StartupTask
TaskId="CaptailStartup"
Enabled="false"
DisplayName="Captail" />
</desktop:Extension>
</Extensions>
</Application>
</Applications>
<Capabilities>
<rescap:Capability Name="runFullTrust" />
<DeviceCapability Name="microphone" />
</Capabilities>
</Package>
64 changes: 64 additions & 0 deletions packaging/msix/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Microsoft Store package

This package channel is separate from Captail's GitHub Installer and Portable
releases. Microsoft Store installs and updates this build. Captail's GitHub
self-updater is disabled at compile time and guarded again at runtime whenever
Windows reports package identity.

## Partner Center identity

- Package name: `faulmit.Captail`
- Publisher: `CN=1BD9448E-C83F-401D-B530-ED5258C6319A`
- Publisher display name: `faulmit`
- Package family name: `faulmit.Captail_ryepxmzt2jqew`
- Store product ID: `9PKVNVLKPTPS`

Do not change package name or publisher. Partner Center rejects packages whose
manifest identity does not match the reserved product.

## Build

From repository root:

```powershell
.\tools\BuildStorePackage.ps1 -Version 0.1.5
```

Output:

```text
artifacts\store\0.1.5\Captail-0.1.5.0-x64.msix
artifacts\store\0.1.5\Captail-0.1.5.0-x64.msixupload
artifacts\store\0.1.5\SHA256SUMS.txt
```

Upload `.msixupload` on Partner Center's **Packages** page. Do not publish this
artifact as a GitHub Release. Microsoft Store signs the accepted package for
distribution.

Generated package is intentionally unsigned. It is ready for Partner Center,
but Windows will not allow direct sideloading until a trusted test certificate
is applied. Store customers receive Microsoft's signed package after
certification.

## Versioning

MSIX requires four numeric components. Captail `0.1.5` becomes package version
`0.1.5.0`. Every Store submission must use a strictly higher package version.
Never reuse a version already submitted to Partner Center.

## Store-specific behavior

- Updates are delivered only by Microsoft Store.
- Footer shows `Microsoft Store` instead of an update action.
- Startup uses the package `windows.startupTask` extension.
- Installer and Portable builds continue using GitHub Releases and HKCU Run.

## Before submission

1. Build package from clean `main` commit.
2. Check `SHA256SUMS.txt` and inspect generated manifest identity.
3. Test install, first launch, tray, capture, replay save, microphone permission,
startup toggle, uninstall, and Store update from previous package version.
4. Complete Partner Center privacy, age rating, properties, screenshots, and
certification notes.
16 changes: 10 additions & 6 deletions src/Captail/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,9 @@ protected override async void OnStartup(StartupEventArgs e)
const bool previewGeometryTest = false;
#endif
bool backgroundLaunch = e.Args.Contains(
"--background",
StringComparer.OrdinalIgnoreCase);
"--background",
StringComparer.OrdinalIgnoreCase) ||
AppDistribution.IsStartupTaskActivation();
bool shutdownExisting = e.Args.Contains(
"--shutdown-existing",
StringComparer.OrdinalIgnoreCase);
Expand Down Expand Up @@ -136,7 +137,7 @@ protected override async void OnStartup(StartupEventArgs e)
{
try
{
Autostart.SetEnabled(true);
await Autostart.SetEnabledAsync(true);
}
catch (Exception exception)
{
Expand Down Expand Up @@ -1307,6 +1308,9 @@ private void OpenSettings()
bool force,
CancellationToken cancellationToken)
{
if (AppDistribution.IsMicrosoftStore)
return Task.FromResult<UpdateRelease?>(null);

#if DEBUG
if (_qaUpdateAvailable)
{
Expand Down Expand Up @@ -1568,7 +1572,7 @@ private async Task<bool> ApplySettingsAsync(

await _pipelineGate.WaitAsync();
Config previous = _config!.Clone();
bool previousAutostart = Autostart.IsEnabled();
bool previousAutostart = await Autostart.IsEnabledAsync();
bool wasRunning = IsReplayRunning;
bool pipelineChanged = !previous.PipelineEquals(candidate);
bool pipelineTouched = false;
Expand All @@ -1595,7 +1599,7 @@ private async Task<bool> ApplySettingsAsync(
Localization.Text("L.Engine.BufferStartFailed"));
}

Autostart.SetEnabled(autostartEnabled);
await Autostart.SetEnabledAsync(autostartEnabled);
_config.Save();
UpdateUiState();

Expand Down Expand Up @@ -1628,7 +1632,7 @@ private async Task<bool> ApplySettingsAsync(
}
try
{
Autostart.SetEnabled(previousAutostart);
await Autostart.SetEnabledAsync(previousAutostart);
}
catch (Exception rollbackException)
{
Expand Down
47 changes: 47 additions & 0 deletions src/Captail/AppDistribution.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using System.Runtime.InteropServices;
using System.Text;
using Windows.ApplicationModel.Activation;

namespace Captail;

internal static class AppDistribution
{
internal const string StoreProductId = "9PKVNVLKPTPS";

#if MICROSOFT_STORE
internal static bool IsMicrosoftStore { get; } = true;
#else
internal static bool IsMicrosoftStore { get; } = HasPackageIdentity();
#endif

internal static bool IsStartupTaskActivation()
{
if (!IsMicrosoftStore)
return false;

try
{
return Windows.ApplicationModel.AppInstance
.GetActivatedEventArgs()?.Kind == ActivationKind.StartupTask;
}
catch (Exception exception)
{
Log.Write($"Could not read package activation: {exception.Message}");
return false;
}
}

private static bool HasPackageIdentity()
{
int length = 0;
return GetCurrentPackageFullName(ref length, null) ==
ErrorInsufficientBuffer;
}

private const int ErrorInsufficientBuffer = 122;

[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
private static extern int GetCurrentPackageFullName(
ref int packageFullNameLength,
StringBuilder? packageFullName);
}
Loading
Loading