<?xml version="1.0" encoding="UTF-8"?>
<!--
  Saetta — HaloPSA inside Microsoft 365 (Outlook).

  Mailbox add-in that opens a pinnable side panel when reading a message.
  Surfaces related HaloPSA tickets for the sender + lets the tech convert
  the email into a new ticket.

  Multi-tenant: published as an AppSource add-in served from saetta.io.
  Authentication uses the same Microsoft Entra ID app registration that
  powers the Teams bot + web dashboard (one identity per human).

  Manifest schema: classic 1.1 + VersionOverrides 1.1 for the modern
  pinnable taskpane experience (desktop + web). VersionOverrides 1.0
  fallback covers older Outlook on Windows.
-->
<OfficeApp
  xmlns="http://schemas.microsoft.com/office/appforoffice/1.1"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:bt="http://schemas.microsoft.com/office/officeappbasictypes/1.0"
  xmlns:mailappor="http://schemas.microsoft.com/office/mailappversionoverrides/1.0"
  xsi:type="MailApp">

  <Id>7c85a58a-9dc4-437a-b98d-f428f031ec14</Id>
  <Version>0.1.0</Version>
  <ProviderName>Vesuvio Labs LLC</ProviderName>
  <DefaultLocale>en-US</DefaultLocale>
  <DisplayName DefaultValue="Saetta" />
  <Description DefaultValue="HaloPSA tickets inside Outlook — see related tickets, convert email to ticket, reply with context." />
  <IconUrl DefaultValue="https://saetta.io/icons/outlook-64.png" />
  <HighResolutionIconUrl DefaultValue="https://saetta.io/icons/outlook-128.png" />
  <SupportUrl DefaultValue="https://saetta.io/support" />

  <AppDomains>
    <AppDomain>https://saetta.io</AppDomain>
  </AppDomains>

  <Hosts>
    <Host Name="Mailbox" />
  </Hosts>

  <Requirements>
    <Sets>
      <Set Name="Mailbox" MinVersion="1.5" />
    </Sets>
  </Requirements>

  <!--
    Classic FormSettings — opens the side panel in legacy Outlook clients
    that don't honour VersionOverrides 1.1.
  -->
  <FormSettings>
    <Form xsi:type="ItemRead">
      <DesktopSettings>
        <SourceLocation DefaultValue="https://saetta.io/outlook/read" />
        <RequestedHeight>250</RequestedHeight>
      </DesktopSettings>
    </Form>
    <Form xsi:type="ItemEdit">
      <DesktopSettings>
        <SourceLocation DefaultValue="https://saetta.io/outlook/compose" />
      </DesktopSettings>
    </Form>
  </FormSettings>

  <!--
    ReadWriteItem: read subject/recipients/body of the message in read AND
    compose mode. Compose-mode body access (item.body.getAsync) requires
    ReadWriteItem. We never request ReadWriteMailbox — Saetta doesn't send
    or alter mail; all ticket writes go to HaloPSA via our backend, and the
    tech sends the actual email from their own Outlook.
  -->
  <Permissions>ReadWriteItem</Permissions>

  <!--
    Activation rules: visible on any read-mode email (related tickets,
    convert flow) AND any compose/reply (link the outgoing email to a Halo
    ticket + log time). Mode="Or" so either context activates the add-in.
  -->
  <Rule xsi:type="RuleCollection" Mode="Or">
    <Rule xsi:type="ItemIs" ItemType="Message" FormType="Read" />
    <Rule xsi:type="ItemIs" ItemType="Message" FormType="Edit" />
  </Rule>

  <DisableEntityHighlighting>false</DisableEntityHighlighting>

  <VersionOverrides xmlns="http://schemas.microsoft.com/office/mailappversionoverrides" xsi:type="VersionOverridesV1_0">
    <VersionOverrides xmlns="http://schemas.microsoft.com/office/mailappversionoverrides/1.1" xsi:type="VersionOverridesV1_1">

      <Requirements>
        <bt:Sets DefaultMinVersion="1.5">
          <bt:Set Name="Mailbox" />
        </bt:Sets>
      </Requirements>

      <Hosts>
        <Host xsi:type="MailHost">

          <DesktopFormFactor>
            <!--
              Pinnable taskpane in the message read surface. Tech opens
              an email → Saetta button in the ribbon → click pins the
              panel. Subsequent emails refresh the panel content
              automatically (Office.context.mailbox.addHandlerAsync
              with ItemChanged).
            -->
            <ExtensionPoint xsi:type="MessageReadCommandSurface">
              <OfficeTab id="TabDefault">
                <Group id="saetta.msgReadGroup">
                  <Label resid="GroupLabel" />
                  <Control xsi:type="Button" id="saetta.openPanel">
                    <Label resid="ButtonLabel" />
                    <Supertip>
                      <Title resid="ButtonTitle" />
                      <Description resid="ButtonDesc" />
                    </Supertip>
                    <Icon>
                      <bt:Image size="16" resid="Icon16" />
                      <bt:Image size="32" resid="Icon32" />
                      <bt:Image size="80" resid="Icon80" />
                    </Icon>
                    <Action xsi:type="ShowTaskpane">
                      <SourceLocation resid="TaskpaneUrl" />
                      <SupportsPinning>true</SupportsPinning>
                    </Action>
                  </Control>
                </Group>
              </OfficeTab>
            </ExtensionPoint>

            <!--
              Compose surface: when the tech writes a reply/new email, the
              Saetta button opens the compose panel to link the outgoing
              email to a Halo ticket and log time. The tech sends the email
              from Outlook; Saetta mirrors it onto the ticket as a public
              note WITHOUT a duplicate Halo-sent copy (alreadySentExternally).
            -->
            <ExtensionPoint xsi:type="MessageComposeCommandSurface">
              <OfficeTab id="TabDefault">
                <Group id="saetta.msgComposeGroup">
                  <Label resid="GroupLabel" />
                  <Control xsi:type="Button" id="saetta.openComposePanel">
                    <Label resid="ButtonLabel" />
                    <Supertip>
                      <Title resid="ComposeButtonTitle" />
                      <Description resid="ComposeButtonDesc" />
                    </Supertip>
                    <Icon>
                      <bt:Image size="16" resid="Icon16" />
                      <bt:Image size="32" resid="Icon32" />
                      <bt:Image size="80" resid="Icon80" />
                    </Icon>
                    <Action xsi:type="ShowTaskpane">
                      <SourceLocation resid="ComposeTaskpaneUrl" />
                      <SupportsPinning>true</SupportsPinning>
                    </Action>
                  </Control>
                </Group>
              </OfficeTab>
            </ExtensionPoint>
          </DesktopFormFactor>

        </Host>
      </Hosts>

      <Resources>
        <bt:Images>
          <bt:Image id="Icon16" DefaultValue="https://saetta.io/icons/outlook-16.png" />
          <bt:Image id="Icon32" DefaultValue="https://saetta.io/icons/outlook-32.png" />
          <bt:Image id="Icon80" DefaultValue="https://saetta.io/icons/outlook-80.png" />
        </bt:Images>
        <bt:Urls>
          <bt:Url id="TaskpaneUrl" DefaultValue="https://saetta.io/outlook/read" />
          <bt:Url id="ComposeTaskpaneUrl" DefaultValue="https://saetta.io/outlook/compose" />
        </bt:Urls>
        <bt:ShortStrings>
          <bt:String id="GroupLabel" DefaultValue="Saetta" />
          <bt:String id="ButtonLabel" DefaultValue="Saetta" />
          <bt:String id="ButtonTitle" DefaultValue="Open Saetta" />
          <bt:String id="ComposeButtonTitle" DefaultValue="Log to HaloPSA" />
        </bt:ShortStrings>
        <bt:LongStrings>
          <bt:String id="ButtonDesc" DefaultValue="See related HaloPSA tickets for this email and convert it to a ticket." />
          <bt:String id="ComposeButtonDesc" DefaultValue="Link this email to a HaloPSA ticket and log time before you send it." />
        </bt:LongStrings>
      </Resources>

      <!--
        Office SSO: tells the Office host which Entra app to mint tokens
        for and which scopes to request when the add-in calls
        OfficeRuntime.auth.getAccessToken(). The resulting token's `aud`
        claim equals the Resource URI; our /api/outlook/auth-bootstrap
        endpoint validates that and exchanges for a Saetta session.

        Same Entra app id as the Teams bot + web dashboard. One identity
        per human across all surfaces.
      -->
      <WebApplicationInfo>
        <Id>5eb5dc8f-94aa-4593-8125-50299812c779</Id>
        <Resource>api://saetta.io/5eb5dc8f-94aa-4593-8125-50299812c779</Resource>
        <Scopes>
          <Scope>access_as_user</Scope>
          <Scope>openid</Scope>
          <Scope>profile</Scope>
        </Scopes>
      </WebApplicationInfo>

    </VersionOverrides>
  </VersionOverrides>

</OfficeApp>
